I'm working with Python Sympy, solving a quadratic, and wanting to print the result using LaTex. For example, if the result is x = (1 + sqrt(3))/2, I would like it to print via LaTex as \frac{1 + \sqrt{3}}{2}. However, Python Sympy either splits this into two fractions, as in \frac{1}{2} + \frac{\sqrt{3}}{2}, OR factors out the half, as in \frac{1}{2}(1 + \sqrt{3}). I have tried to return the numerator via sympy.fraction(expr) and have viewed other articles (Sympy - fraction manipulation and others), but none were able to produce the result.
Check out how to override the default printers.
import sympy
from sympy.printing.latex import LatexPrinter # necessary because latex is both a function and a module
class CustomLatexPrinter(LatexPrinter):
def _print_Add(self, expr):
n, d = expr.as_numer_denom()
if d == sympy.S.One:
# defer to the default printing mechanism
super()._print_Add(expr)
return
return r'\frac{%s}{%s}' % (sympy.latex(n), sympy.latex(d))
# doing this should override the default latex printer globally
# adopted from "Examples of overloading StrPrinter" in the sympy documentation
sympy.printing.latex = lambda self: CustomLatexPrinter().doprint(self)
print(sympy.printing.latex((1 + sympy.sqrt(3)) / 2)) # \frac{1 + \sqrt{3}}{2}
Related
I will have data which uses degrees for the trigonometric functions.
I will use sympy and since it uses radians for the trigonometric functions, I want to be able to convert and use degrees.
But, I will not know which symbol variable is been used as input to the trigonometric function.
So , I will have something like:
import sympy
from sympy import mpmath
a = 2
b = 30
a,b = sympy.symbols('a b')
expr = 'sqrt(a + cos(b))'
expres = sympy.sympify(expr)
print(expres.atoms(sympy.cos))
The b is 30 and it is in degrees (so, in the cos(b) computations it must be degrees, not radians as sympy expects).
But, as I said, another time the program runs, it will use another symbol variable for trigonometric.Or, more than one trigonometric functions.
I thought if using atoms in order to find if in the expression I have trigonometric functions.And then , somehow , use degrees instead of radians wherever the corresponding symbol variables is been used.
Is there a way to do this?
Arguably the most clean way to avoid this problem is to tell sympify to use custom definitions for selected symbols/strings, e.g., like this:
from sympy.abc import *
from sympy import sin, pi, Lambda, sympify
sin_degree = Lambda(x, sin(x*pi/180))
degree_trigs = {"sin": sin_degree}
expr_string = "sin(a) + sin(b**d + exp(c))"
expr = sympify(expr_string, locals=degree_trigs)
print(expr)
This returns:
sin(pi*a/180) + sin(pi*(b**d/180 + exp(c)/180))
You can use subs with functions, e.g., like this:
from sympy.abc import *
from sympy import sin, exp, pi, Lambda
sin_degree = Lambda(x, sin(x*pi/180))
expr = sin(a) + sin(b**d + exp(c))
print( expr.subs(sin,sin_degree) )
This returns:
sin(pi*a/180) + sin(pi*(b**d/180 + exp(c)/180))
The answer to 2^(-1/3) are three roots:
0.79370, -0.39685-0.68736i and 0.39685+0.68736i (approximately)
See the correct answer at Wolfram Alpha.
I know several languages that supports complex numbers, but they all only return the first of the three results:
Python:
>>> complex(2,0)**(-1/3)
(0.7937005259840998-0j)
Octave:
>> (2+0i)^(-1/3)
ans = 0.79370
Julia:
julia> complex(2,0)^(-1/3)
0.7937005259840998 + 0.0im
What I'm looking for is something along the lines of:
>> 2^(-1/3)
[0.79370+0i, -0.39685-0.68736i, 0.39685+0.68736i]
Is there a programming language (with a REPL) that will correctly return all three roots, without having to resort to any special modules or libraries, that also has an open source implementation available?
As many comments explained, wanting a general purpose language to give by default the result from every branch of the complex root function is probably a tall order. But Julia allows specializing/overloading operators very naturally (as even the out-of-the-box implementation is often written in Julia). Specifically:
using Roots,Polynomials # Might need to Pkg.add("Roots") first
import Base: ^
^{T<:AbstractFloat}(b::T, r::Rational{Int64}) =
roots(poly([0])^r.den - b^abs(r.num)).^sign(r.num)
And now when trying to raise a float to a rational power:
julia> 2.0^(-1//3)
3-element Array{Complex{Float64},1}:
-0.39685-0.687365im
-0.39685+0.687365im
0.793701-0.0im
Note that specializing the definition of ^ to rational exponents solves the rounding problem mentioned in the comments.
Here is how to solve for all of the roots of b1/n via the roots the polynomial xn - b with Matlab's roots or Octave's roots:
b = 2;
n = -3; % for b^(1/n)
c = [1 zeros(1,abs(n)-1) -b];
r = roots(c).^sign(n);
which returns
r =
-0.396850262992050 - 0.687364818499301i
-0.396850262992050 + 0.687364818499301i
0.793700525984100 + 0.000000000000000i
Alternatively, using roots of unity (not sure how numerically robust this is):
b = 2;
n = -3;
n0 = abs(n);
r0 = b^(1/n0);
w = exp(2*pi*1i/n0);
r = (r0*w.^(0:n0-1).').^sign(n)
Or using Matlab's Symbolic Math toolbox:
b = 2;
n = -3;
c = [1 zeros(1,abs(n)-1) -b];
r = solve(poly2sym(c)).^sign(n)
which returns:
r =
2^(2/3)/2
2^(2/3)/(2*((3^(1/2)*1i)/2 - 1/2))
-2^(2/3)/(2*((3^(1/2)*1i)/2 + 1/2))
In certain cases you might also find nthroot helpful (Octave documentation).
Im trying to compile an expression that contains an UndefinedFunction which has an implementation provided. (Alternatively: an expression which contains a Symbol which represents a call to an external numerical function)
Is there a way to do this? Either with autowrap or codegen or perhaps with some manual editing of the generated files?
The following naive example does not work:
import sympy as sp
import numpy as np
from sympy.abc import *
from sympy.utilities.lambdify import implemented_function
from sympy.utilities.autowrap import autowrap, ufuncify
def g_implementation(a):
"""represents some numerical function"""
return a*5
# sympy wrapper around the above function
g = implemented_function('g', g_implementation)
# some random expression using the above function
e = (x+g(a))**2+100
# try to compile said expression
f = autowrap(e, backend='cython')
# fails with "undefined reference to `g'"
EDIT:
I have several large Sympy expressions
The expressions are generated automatically (via differentiation and such)
The expressions contain some "implemented UndefinedFunctions" that call some numerical functions (i.e. NOT Sympy expressions)
The final script/program that has to evaluate the expressions for some input will be called quite often. That means that evaluating the expression in Sympy (via evalf) is definitely not feasible. Even compiling just in time (lambdify, autowrap, ufuncify, numba.jit) produces too much of an overhead.
Basically I want to create a binary python extension for those expressions without having to implement them by hand in C, which I consider too error prone.
OS is Windows 7 64bit
You may want to take a look at this answer about serialization of SymPy lambdas (generated by lambdify).
It's not exactly what you asked but may alleviate your problem with startup performance. Then lambdify-ied functions will mostly count only execution time.
You may also take a look at Theano. It has nice integration with SymPy.
Ok, this could do the trick, I hope, if not let me know and I'll try again.
I compare a compiled version of an expression using Cython against the lambdified expression.
from sympy.utilities.autowrap import autowrap
from sympy import symbols, lambdify
def wraping(expression):
return autowrap(expression, backend='cython')
def lamFunc(expression, x, y):
return lambdify([x,y], expr)
x, y = symbols('x y')
expr = ((x - y)**(25)).expand()
print expr
binary_callable = wraping(expr)
print binary_callable(1, 2)
lamb = lamFunc(expr, x, y)
print lamb(1,2)
which outputs:
x**25 - 25*x**24*y + 300*x**23*y**2 - 2300*x**22*y**3 + 12650*x**21*y**4 - 53130*x**20*y**5 + 177100*x**19*y**6 - 480700*x**18*y**7 + 1081575*x**17*y**8 - 2042975*x**16*y**9 + 3268760*x**15*y**10 - 4457400*x**14*y**11 + 5200300*x**13*y**12 - 5200300*x**12*y**13 + 4457400*x**11*y**14 - 3268760*x**10*y**15 + 2042975*x**9*y**16 - 1081575*x**8*y**17 + 480700*x**7*y**18 - 177100*x**6*y**19 + 53130*x**5*y**20 - 12650*x**4*y**21 + 2300*x**3*y**22 - 300*x**2*y**23 + 25*x*y**24 - y**25
-1.0
-1
If I time the execution times the autowraped function is 10x faster (depending on the problem I have also observed cases where the factor was as little as two):
%timeit binary_callable(12, 21)
100000 loops, best of 3: 2.87 µs per loop
%timeit lamb(12, 21)
100000 loops, best of 3: 28.7 µs per loop
So here wraping(expr) wraps your expression expr and returns a wrapped object binary_callable. This you can use at any time to do numerical evaluation.
EDIT: I have done this on Linux/Ubuntu and Windows OS, both seem to work fine!
For a project in one of my classes we have to output numbers up to five decimal places.It is possible that the output will be a complex number and I am unable to figure out how to output a complex number with five decimal places. For floats I know it is just:
print "%0.5f"%variable_name
Is there something similar for complex numbers?
You could do it as is shown below using the str.format() method:
>>> n = 3.4+2.3j
>>> n
(3.4+2.3j)
>>> '({0.real:.2f} + {0.imag:.2f}i)'.format(n)
'(3.40 + 2.30i)'
>>> '({c.real:.2f} + {c.imag:.2f}i)'.format(c=n)
'(3.40 + 2.30i)'
To make it handle both positive and negative imaginary portions properly, you would need a (even more) complicated formatting operation:
>>> n = 3.4-2.3j
>>> n
(3.4-2.3j)
>>> '({0:.2f} {1} {2:.2f}i)'.format(n.real, '+-'[n.imag < 0], abs(n.imag))
'(3.40 - 2.30i)'
Update - Easier Way
Although you cannot use f as a presentation type for complex numbers using the string formatting operator %:
n1 = 3.4+2.3j
n2 = 3.4-2.3j
try:
print('test: %.2f' % n1)
except Exception as exc:
print('{}: {}'.format(type(exc).__name__, exc))
Output:
TypeError: float argument required, not complex
You can however use it with complex numbers via the str.format() method. This isn't explicitly documented, but is implied by the Format Specification Mini-Language documentation which just says:
'f' Fixed point. Displays the number as a fixed-point number. The default precision is 6.
. . .so it's easy to overlook.
In concrete terms, the following works in both Python 2.7.14 and 3.4.6:
print('n1: {:.2f}'.format(n1))
print('n2: {:.2f}'.format(n2))
Output:
n1: 3.10+4.20j
n2: 3.10-4.20j
This doesn't give you quite the control the code in my original answer does, but it's certainly much more concise (and handles both positive and negative imaginary parts automatically).
Update 2 - f-strings
Formatted string literals (aka f-strings) were added in Python 3.6, which means it could also be done like this in that version or later:
print(f'n1: {n1:.2f}') # -> n1: 3.40+2.30j
print(f'n2: {n2:.3f}') # -> n2: 3.400-2.300j
In Python 3.8.0, support for an = specifier was added to f-strings, allowing you to write:
print(f'{n1=:.2f}') # -> n1=3.40+2.30j
print(f'{n2=:.3f}') # -> n2=3.400-2.300j
Neither String Formatting Operations - i.e. the modulo (%) operator) -
nor the newer str.format() Format String Syntax support complex types.
However it is possible to call the __format__ method of all built in numeric types directly.
Here is an example:
>>> i = -3 # int
>>> l = -33L # long (only Python 2.X)
>>> f = -10./3 # float
>>> c = - 1./9 - 2.j/9 # complex
>>> [ x.__format__('.3f') for x in (i, l, f, c)]
['-3.000', '-33.000', '-3.333', '-0.111-0.222j']
Note, that this works well with negative imaginary parts too.
For questions like this, the Python documentation should be your first stop. Specifically, have a look at the section on string formatting. It lists all the string format codes; there isn't one for complex numbers.
What you can do is format the real and imaginary parts of the number separately, using x.real and x.imag, and print it out in a + bi form.
>>> n = 3.4 + 2.3j
>>> print '%05f %05fi' % (n.real, n.imag)
3.400000 2.300000i
As of Python 2.6 you can define how objects of your own classes respond to format strings. So, you can define a subclass of complex that can be formatted. Here's an example:
>>> class Complex_formatted(complex):
... def __format__(self, fmt):
... cfmt = "({:" + fmt + "}{:+" + fmt + "}j)"
... return cfmt.format(self.real, self.imag)
...
>>> z1 = Complex_formatted(.123456789 + 123.456789j)
>>> z2 = Complex_formatted(.123456789 - 123.456789j)
>>> "My complex numbers are {:0.5f} and {:0.5f}.".format(z1, z2)
'My complex numbers are (0.12346+123.45679j) and (0.12346-123.45679j).'
>>> "My complex numbers are {:0.6f} and {:0.6f}.".format(z1, z2)
'My complex numbers are (0.123457+123.456789j) and (0.123457-123.456789j).'
Objects of this class behave exactly like complex numbers except they take more space and operate more slowly; reader beware.
Check this out:
np.set_printoptions(precision=2) # Rounds up to 2 decimals all float expressions
I've successfully printed my complexfloat's expressions:
# Show poles and zeros
print( "zeros = ", zeros_H , "\n")
print( "poles = ", poles_H )
out before:
zeros = [-0.8 +0.6j -0.8 -0.6j -0.66666667+0.j ]
poles = [-0.81542318+0.60991027j -0.81542318-0.60991027j -0.8358203 +0.j ]
out after:
zeros = [-0.8 +0.6j -0.8 -0.6j -0.67+0.j ]
poles = [-0.82+0.61j -0.82-0.61j -0.84+0.j ]
All I need is to check, using python, if a string is a valid math expression or not.
For simplicity let's say I just need + - * / operators (+ - as unary too) with numbers and nested parenthesis. I add also simple variable names for completeness.
So I can test this way:
test("-3 * (2 + 1)") #valid
test("-3 * ") #NOT valid
test("v1 + v2") #valid
test("v2 - 2v") #NOT valid ("2v" not a valid variable name)
I tried pyparsing but just trying the example: "simple algebraic expression parser, that performs +,-,*,/ and ^ arithmetic operations" I get passed invalid code and also trying to fix it I always get wrong syntaxes being parsed without raising Exceptions
just try:
>>>test('9', 9)
9 qwerty = 9.0 ['9'] => ['9']
>>>test('9 qwerty', 9)
9 qwerty = 9.0 ['9'] => ['9']
both test pass... o_O
Any advice?
This is because the pyparsing code allows functions. (And by the way, it does a lot more than what you need, i.e. create a stack and evaluate that.)
For starters, you could remove pi and ident (and possibly something else I'm missing right now) from the code to disallow characters.
The reason is different: PyParsing parsers won't try to consume the whole input by default. You have to add + StringEnd() (and import it, of course) to the end of expr to make it fail if it can't parse the whole input. In that case, pyparsing.ParseException will be raised. (Source: http://pyparsing-public.wikispaces.com/FAQs)
If you care to learn a bit of parsing, what you need can propably be built in less than thirty lines with any decent parsing library (I like LEPL).
You could try building a simple parser yourself to tokenize the string of the arithmetic expression and then build an expression tree, if the tree is valid (the leaves are all operands and the internal nodes are all operators) then you can say that the expression is valid.
The basic concept is to make a few helper functions to create your parser.
def extract() will get the next character from the expression
def peek() similar to extract but used if there is no whitespace to check the next character
get_expression()
get_next_token()
Alternatively if you can guarantee whitespace between characters you could use split() to do all the tokenizing.
Then you build your tree and evaluate if its structured correctly
Try this for more info: http://effbot.org/zone/simple-top-down-parsing.htm
Why not just evaluate it and catch the syntax error?
from math import *
def validateSyntax(expression):
functions = {'__builtins__': None}
variables = {'__builtins__': None}
functions = {'acos': acos,
'asin': asin,
'atan': atan,
'atan2': atan2,
'ceil': ceil,
'cos': cos,
'cosh': cosh,
'degrees': degrees,
'exp': exp,
'fabs':fabs,
'floor': floor,
'fmod': fmod,
'frexp': frexp,
'hypot': hypot,
'ldexp': ldexp,
'log': log,
'log10': log10,
'modf': modf,
'pow': pow,
'radians': radians,
'sin': sin,
'sinh': sinh,
'sqrt': sqrt,
'tan': tan,
'tanh': tanh}
variables = {'e': e, 'pi': pi}
try:
eval(expression, variables, functions)
except (SyntaxError, NameError, ZeroDivisionError):
return False
else:
return True
Here are some samples:
> print validSyntax('a+b-1') # a, b are undefined, so a NameError arises.
> False
> print validSyntax('1 + 2')
> True
> print validSyntax('1 - 2')
> True
> print validSyntax('1 / 2')
> True
> print validSyntax('1 * 2')
> True
> print validSyntax('1 +/ 2')
> False
> print validSyntax('1 + (2')
> False
> print validSyntax('import os')
> False
> print validSyntax('print "asd"')
> False
> print validSyntax('import os; os.delete("~\test.txt")')
> False # And the file was not removed
It's restricted to only mathematical operations, so it should work a bit better than a crude eval.
Adding parseAll=True to the call to parseString will convert this parser into a validator.
If you are interested in modifying a custom math evaluator engine written in Python so that it is a validator instead, you could start out with Evaluator 2.0 (Python 3.x) and Math_Evaluator (Python 2.x). They are not ready-made solutions but would allow you to fully customize whatever it is you are trying to do exactly using (hopefully) easy-to-read Python code. Note that "and" & "or" are treated as operators.