Utilities for Calculus¶
This module defines helper functions which are used for simplifications and display of symbolic expressions.
AUTHORS:
- Michal Bejger (2015) : class - ExpressionNice
- Eric Gourgoulhon (2015, 2017) : simplification functions 
- Travis Scrimshaw (2016): review tweaks 
- Marius Gerbershagen (2022) : skip simplification of expressions with a single number or symbolic variable 
- class sage.manifolds.utilities.ExpressionNice(ex)[source]¶
- Bases: - Expression- Subclass of - Expressionfor a “human-friendly” display of partial derivatives and the possibility to shorten the display by skipping the arguments of symbolic functions.- INPUT: - ex– symbolic expression
 - EXAMPLES: - An expression formed with callable symbolic expressions: - sage: var('x y z') (x, y, z) sage: f = function('f')(x, y) sage: g = f.diff(y).diff(x) sage: h = function('h')(y, z) sage: k = h.diff(z) sage: fun = x*g + y*(k-z)^2 - >>> from sage.all import * >>> var('x y z') (x, y, z) >>> f = function('f')(x, y) >>> g = f.diff(y).diff(x) >>> h = function('h')(y, z) >>> k = h.diff(z) >>> fun = x*g + y*(k-z)**Integer(2) - The standard Pynac display of partial derivatives: - sage: fun y*(z - diff(h(y, z), z))^2 + x*diff(f(x, y), x, y) sage: latex(fun) y {\left(z - \frac{\partial}{\partial z}h\left(y, z\right)\right)}^{2} + x \frac{\partial^{2}}{\partial x\partial y}f\left(x, y\right) - >>> from sage.all import * >>> fun y*(z - diff(h(y, z), z))^2 + x*diff(f(x, y), x, y) >>> latex(fun) y {\left(z - \frac{\partial}{\partial z}h\left(y, z\right)\right)}^{2} + x \frac{\partial^{2}}{\partial x\partial y}f\left(x, y\right) - With - ExpressionNice, the Pynac notation- D[...]is replaced by textbook-like notation:- sage: from sage.manifolds.utilities import ExpressionNice sage: ExpressionNice(fun) y*(z - d(h)/dz)^2 + x*d^2(f)/dxdy sage: latex(ExpressionNice(fun)) y {\left(z - \frac{\partial\,h}{\partial z}\right)}^{2} + x \frac{\partial^2\,f}{\partial x\partial y} - >>> from sage.all import * >>> from sage.manifolds.utilities import ExpressionNice >>> ExpressionNice(fun) y*(z - d(h)/dz)^2 + x*d^2(f)/dxdy >>> latex(ExpressionNice(fun)) y {\left(z - \frac{\partial\,h}{\partial z}\right)}^{2} + x \frac{\partial^2\,f}{\partial x\partial y} - An example when function variables are themselves functions: - sage: f = function('f')(x, y) sage: g = function('g')(x, f) # the second variable is the function f sage: fun = (g.diff(x))*x - x^2*f.diff(x,y) sage: fun -x^2*diff(f(x, y), x, y) + (diff(f(x, y), x)*D[1](g)(x, f(x, y)) + D[0](g)(x, f(x, y)))*x sage: ExpressionNice(fun) -x^2*d^2(f)/dxdy + (d(f)/dx*d(g)/d(f(x, y)) + d(g)/dx)*x sage: latex(ExpressionNice(fun)) -x^{2} \frac{\partial^2\,f}{\partial x\partial y} + {\left(\frac{\partial\,f}{\partial x} \frac{\partial\,g}{\partial \left( f\left(x, y\right) \right)} + \frac{\partial\,g}{\partial x}\right)} x - >>> from sage.all import * >>> f = function('f')(x, y) >>> g = function('g')(x, f) # the second variable is the function f >>> fun = (g.diff(x))*x - x**Integer(2)*f.diff(x,y) >>> fun -x^2*diff(f(x, y), x, y) + (diff(f(x, y), x)*D[1](g)(x, f(x, y)) + D[0](g)(x, f(x, y)))*x >>> ExpressionNice(fun) -x^2*d^2(f)/dxdy + (d(f)/dx*d(g)/d(f(x, y)) + d(g)/dx)*x >>> latex(ExpressionNice(fun)) -x^{2} \frac{\partial^2\,f}{\partial x\partial y} + {\left(\frac{\partial\,f}{\partial x} \frac{\partial\,g}{\partial \left( f\left(x, y\right) \right)} + \frac{\partial\,g}{\partial x}\right)} x - Note that - D[1](g)(x, f(x,y))is rendered as- d(g)/d(f(x, y)).- An example with multiple differentiations: - sage: fun = f.diff(x,x,y,y,x)*x sage: fun x*diff(f(x, y), x, x, x, y, y) sage: ExpressionNice(fun) x*d^5(f)/dx^3dy^2 sage: latex(ExpressionNice(fun)) x \frac{\partial^5\,f}{\partial x ^ 3\partial y ^ 2} - >>> from sage.all import * >>> fun = f.diff(x,x,y,y,x)*x >>> fun x*diff(f(x, y), x, x, x, y, y) >>> ExpressionNice(fun) x*d^5(f)/dx^3dy^2 >>> latex(ExpressionNice(fun)) x \frac{\partial^5\,f}{\partial x ^ 3\partial y ^ 2} - Parentheses are added around powers of partial derivatives to avoid any confusion: - sage: fun = f.diff(y)^2 sage: fun diff(f(x, y), y)^2 sage: ExpressionNice(fun) (d(f)/dy)^2 sage: latex(ExpressionNice(fun)) \left(\frac{\partial\,f}{\partial y}\right)^{2} - >>> from sage.all import * >>> fun = f.diff(y)**Integer(2) >>> fun diff(f(x, y), y)^2 >>> ExpressionNice(fun) (d(f)/dy)^2 >>> latex(ExpressionNice(fun)) \left(\frac{\partial\,f}{\partial y}\right)^{2} - The explicit mention of function arguments can be omitted for the sake of brevity: - sage: fun = fun*f sage: ExpressionNice(fun) f(x, y)*(d(f)/dy)^2 sage: Manifold.options.omit_function_arguments=True sage: ExpressionNice(fun) f*(d(f)/dy)^2 sage: latex(ExpressionNice(fun)) f \left(\frac{\partial\,f}{\partial y}\right)^{2} sage: Manifold.options._reset() sage: ExpressionNice(fun) f(x, y)*(d(f)/dy)^2 sage: latex(ExpressionNice(fun)) f\left(x, y\right) \left(\frac{\partial\,f}{\partial y}\right)^{2} - >>> from sage.all import * >>> fun = fun*f >>> ExpressionNice(fun) f(x, y)*(d(f)/dy)^2 >>> Manifold.options.omit_function_arguments=True >>> ExpressionNice(fun) f*(d(f)/dy)^2 >>> latex(ExpressionNice(fun)) f \left(\frac{\partial\,f}{\partial y}\right)^{2} >>> Manifold.options._reset() >>> ExpressionNice(fun) f(x, y)*(d(f)/dy)^2 >>> latex(ExpressionNice(fun)) f\left(x, y\right) \left(\frac{\partial\,f}{\partial y}\right)^{2} 
- class sage.manifolds.utilities.SimplifyAbsTrig(ex)[source]¶
- Bases: - ExpressionTreeWalker- Class for simplifying absolute values of cosines or sines (in the real domain), by walking the expression tree. - The end user interface is the function - simplify_abs_trig().- INPUT: - ex– a symbolic expression
 - EXAMPLES: - Let us consider the following symbolic expression with some assumption on the range of the variable \(x\): - sage: assume(pi/2<x, x<pi) sage: a = abs(cos(x)) + abs(sin(x)) - >>> from sage.all import * >>> assume(pi/Integer(2)<x, x<pi) >>> a = abs(cos(x)) + abs(sin(x)) - The method - simplify_full()is ineffective on such an expression:- sage: a.simplify_full() abs(cos(x)) + abs(sin(x)) - >>> from sage.all import * >>> a.simplify_full() abs(cos(x)) + abs(sin(x)) - We construct a - SimplifyAbsTrigobject- sfrom the symbolic expression- a:- sage: from sage.manifolds.utilities import SimplifyAbsTrig sage: s = SimplifyAbsTrig(a) - >>> from sage.all import * >>> from sage.manifolds.utilities import SimplifyAbsTrig >>> s = SimplifyAbsTrig(a) - We use the - __call__method to walk the expression tree and produce a correctly simplified expression, given that \(x\in(\pi/2, \pi)\):- sage: s() -cos(x) + sin(x) - >>> from sage.all import * >>> s() -cos(x) + sin(x) - Calling the simplifier - swith an expression actually simplifies this expression:- sage: s(a) # same as s() since s is built from a -cos(x) + sin(x) sage: s(abs(cos(x/2)) + abs(sin(x/2))) # pi/4 < x/2 < pi/2 cos(1/2*x) + sin(1/2*x) sage: s(abs(cos(2*x)) + abs(sin(2*x))) # pi < 2 x < 2*pi abs(cos(2*x)) - sin(2*x) sage: s(abs(sin(2+abs(cos(x))))) # nested abs(sin_or_cos(...)) sin(-cos(x) + 2) - >>> from sage.all import * >>> s(a) # same as s() since s is built from a -cos(x) + sin(x) >>> s(abs(cos(x/Integer(2))) + abs(sin(x/Integer(2)))) # pi/4 < x/2 < pi/2 cos(1/2*x) + sin(1/2*x) >>> s(abs(cos(Integer(2)*x)) + abs(sin(Integer(2)*x))) # pi < 2 x < 2*pi abs(cos(2*x)) - sin(2*x) >>> s(abs(sin(Integer(2)+abs(cos(x))))) # nested abs(sin_or_cos(...)) sin(-cos(x) + 2) - See also - simplify_abs_trig()for more examples with- SimplifyAbsTrigat work.- composition(ex, operator)[source]¶
- This is the only method of the base class - ExpressionTreeWalkerthat is reimplemented, since it manages the composition of- abswith- cosor- sin.- INPUT: - ex– a symbolic expression
- operator– an operator
 - OUTPUT: - a symbolic expression, equivalent to - exwith- abs(cos(...))and- abs(sin(...))simplified, according to the range of their argument.
 - EXAMPLES: - sage: from sage.manifolds.utilities import SimplifyAbsTrig sage: assume(-pi/2 < x, x<0) sage: a = abs(sin(x)) sage: s = SimplifyAbsTrig(a) sage: a.operator() abs sage: s.composition(a, a.operator()) sin(-x) - >>> from sage.all import * >>> from sage.manifolds.utilities import SimplifyAbsTrig >>> assume(-pi/Integer(2) < x, x<Integer(0)) >>> a = abs(sin(x)) >>> s = SimplifyAbsTrig(a) >>> a.operator() abs >>> s.composition(a, a.operator()) sin(-x) - sage: a = exp(function('f')(x)) # no abs(sin_or_cos(...)) sage: a.operator() exp sage: s.composition(a, a.operator()) e^f(x) - >>> from sage.all import * >>> a = exp(function('f')(x)) # no abs(sin_or_cos(...)) >>> a.operator() exp >>> s.composition(a, a.operator()) e^f(x) - sage: forget() # no longer any assumption on x sage: a = abs(cos(sin(x))) # simplifiable since -1 <= sin(x) <= 1 sage: s.composition(a, a.operator()) cos(sin(x)) sage: a = abs(sin(cos(x))) # not simplifiable sage: s.composition(a, a.operator()) abs(sin(cos(x))) - >>> from sage.all import * >>> forget() # no longer any assumption on x >>> a = abs(cos(sin(x))) # simplifiable since -1 <= sin(x) <= 1 >>> s.composition(a, a.operator()) cos(sin(x)) >>> a = abs(sin(cos(x))) # not simplifiable >>> s.composition(a, a.operator()) abs(sin(cos(x))) 
 
- class sage.manifolds.utilities.SimplifySqrtReal(ex)[source]¶
- Bases: - ExpressionTreeWalker- Class for simplifying square roots in the real domain, by walking the expression tree. - The end user interface is the function - simplify_sqrt_real().- INPUT: - ex– a symbolic expression
 - EXAMPLES: - Let us consider the square root of an exact square under some assumption: - sage: assume(x<1) sage: a = sqrt(x^2-2*x+1) - >>> from sage.all import * >>> assume(x<Integer(1)) >>> a = sqrt(x**Integer(2)-Integer(2)*x+Integer(1)) - The method - simplify_full()is ineffective on such an expression:- sage: a.simplify_full() sqrt(x^2 - 2*x + 1) - >>> from sage.all import * >>> a.simplify_full() sqrt(x^2 - 2*x + 1) - and the more aggressive method - canonicalize_radical()yields a wrong result, given that \(x<1\):- sage: a.canonicalize_radical() # wrong output! x - 1 - >>> from sage.all import * >>> a.canonicalize_radical() # wrong output! x - 1 - We construct a - SimplifySqrtRealobject- sfrom the symbolic expression- a:- sage: from sage.manifolds.utilities import SimplifySqrtReal sage: s = SimplifySqrtReal(a) - >>> from sage.all import * >>> from sage.manifolds.utilities import SimplifySqrtReal >>> s = SimplifySqrtReal(a) - We use the - __call__method to walk the expression tree and produce a correctly simplified expression:- sage: s() -x + 1 - >>> from sage.all import * >>> s() -x + 1 - Calling the simplifier - swith an expression actually simplifies this expression:- sage: s(a) # same as s() since s is built from a -x + 1 sage: s(sqrt(x^2)) abs(x) sage: s(sqrt(1+sqrt(x^2-2*x+1))) # nested sqrt's sqrt(-x + 2) - >>> from sage.all import * >>> s(a) # same as s() since s is built from a -x + 1 >>> s(sqrt(x**Integer(2))) abs(x) >>> s(sqrt(Integer(1)+sqrt(x**Integer(2)-Integer(2)*x+Integer(1)))) # nested sqrt's sqrt(-x + 2) - Another example where both - simplify_full()and- canonicalize_radical()fail:- sage: b = sqrt((x-1)/(x-2))*sqrt(1-x) sage: b.simplify_full() # does not simplify sqrt(-x + 1)*sqrt((x - 1)/(x - 2)) sage: b.canonicalize_radical() # wrong output, given that x<1 (I*x - I)/sqrt(x - 2) sage: SimplifySqrtReal(b)() # OK, given that x<1 -(x - 1)/sqrt(-x + 2) - >>> from sage.all import * >>> b = sqrt((x-Integer(1))/(x-Integer(2)))*sqrt(Integer(1)-x) >>> b.simplify_full() # does not simplify sqrt(-x + 1)*sqrt((x - 1)/(x - 2)) >>> b.canonicalize_radical() # wrong output, given that x<1 (I*x - I)/sqrt(x - 2) >>> SimplifySqrtReal(b)() # OK, given that x<1 -(x - 1)/sqrt(-x + 2) - See also - simplify_sqrt_real()for more examples with- SimplifySqrtRealat work.- arithmetic(ex, operator)[source]¶
- This is the only method of the base class - ExpressionTreeWalkerthat is reimplemented, since square roots are considered as arithmetic operations with- operator=- powand- ex.operands()[1]=- 1/2or- -1/2.- INPUT: - ex– a symbolic expression
- operator– an arithmetic operator
 - OUTPUT: - a symbolic expression, equivalent to - exwith square roots simplified
 - EXAMPLES: - sage: from sage.manifolds.utilities import SimplifySqrtReal sage: a = sqrt(x^2+2*x+1) sage: s = SimplifySqrtReal(a) sage: a.operator() <built-in function pow> sage: s.arithmetic(a, a.operator()) abs(x + 1) - >>> from sage.all import * >>> from sage.manifolds.utilities import SimplifySqrtReal >>> a = sqrt(x**Integer(2)+Integer(2)*x+Integer(1)) >>> s = SimplifySqrtReal(a) >>> a.operator() <built-in function pow> >>> s.arithmetic(a, a.operator()) abs(x + 1) - sage: a = x + 1 # no square root sage: s.arithmetic(a, a.operator()) x + 1 - >>> from sage.all import * >>> a = x + Integer(1) # no square root >>> s.arithmetic(a, a.operator()) x + 1 - sage: a = x + 1 + sqrt(function('f')(x)^2) sage: s.arithmetic(a, a.operator()) x + abs(f(x)) + 1 - >>> from sage.all import * >>> a = x + Integer(1) + sqrt(function('f')(x)**Integer(2)) >>> s.arithmetic(a, a.operator()) x + abs(f(x)) + 1 
 
- sage.manifolds.utilities.exterior_derivative(form)[source]¶
- Exterior derivative of a differential form. - INPUT: - form– a differential form; this must an instance of either- DiffScalarFieldfor a 0-form (scalar field)
- DiffFormParalfor a \(p\)-form (\(p\geq 1\)) on a parallelizable manifold
- DiffFormfor a a \(p\)-form (\(p\geq 1\)) on a non-parallelizable manifold
 
 - OUTPUT: - the \((p+1)\)-form that is the exterior derivative of - form
 - EXAMPLES: - Exterior derivative of a scalar field (0-form): - sage: from sage.manifolds.utilities import exterior_derivative sage: M = Manifold(3, 'M') sage: X.<x,y,z> = M.chart() sage: f = M.scalar_field({X: x+y^2+z^3}, name='f') sage: df = exterior_derivative(f); df 1-form df on the 3-dimensional differentiable manifold M sage: df.display() df = dx + 2*y dy + 3*z^2 dz - >>> from sage.all import * >>> from sage.manifolds.utilities import exterior_derivative >>> M = Manifold(Integer(3), 'M') >>> X = M.chart(names=('x', 'y', 'z',)); (x, y, z,) = X._first_ngens(3) >>> f = M.scalar_field({X: x+y**Integer(2)+z**Integer(3)}, name='f') >>> df = exterior_derivative(f); df 1-form df on the 3-dimensional differentiable manifold M >>> df.display() df = dx + 2*y dy + 3*z^2 dz - An alias is - xder:- sage: from sage.manifolds.utilities import xder sage: df == xder(f) True - >>> from sage.all import * >>> from sage.manifolds.utilities import xder >>> df == xder(f) True - Exterior derivative of a 1-form: - sage: a = M.one_form(name='a') sage: a[:] = [x+y*z, x-y*z, x*y*z] sage: da = xder(a); da 2-form da on the 3-dimensional differentiable manifold M sage: da.display() da = (-z + 1) dx∧dy + (y*z - y) dx∧dz + (x*z + y) dy∧dz sage: dda = xder(da); dda 3-form dda on the 3-dimensional differentiable manifold M sage: dda.display() dda = 0 - >>> from sage.all import * >>> a = M.one_form(name='a') >>> a[:] = [x+y*z, x-y*z, x*y*z] >>> da = xder(a); da 2-form da on the 3-dimensional differentiable manifold M >>> da.display() da = (-z + 1) dx∧dy + (y*z - y) dx∧dz + (x*z + y) dy∧dz >>> dda = xder(da); dda 3-form dda on the 3-dimensional differentiable manifold M >>> dda.display() dda = 0 
- sage.manifolds.utilities.set_axes_labels(graph, xlabel, ylabel, zlabel, **kwds)[source]¶
- Set axes labels for a 3D graphics object - graph.- This is a workaround for the lack of axes labels in 3D plots. This sets the labels as - text3d()objects at locations determined from the bounding box of the graphic object- graph.- INPUT: - graph–- Graphics3d; a 3D graphic object
- xlabel– string for the x-axis label
- ylabel– string for the y-axis label
- zlabel– string for the z-axis label
- **kwds– options (e.g. color) for text3d
 - OUTPUT: the 3D graphic object with text3d labels added - EXAMPLES: - sage: # needs sage.plot sage: g = sphere() sage: g.all [Graphics3d Object] sage: from sage.manifolds.utilities import set_axes_labels sage: ga = set_axes_labels(g, 'X', 'Y', 'Z', color='red') sage: ga.all # the 3D frame has now axes labels [Graphics3d Object, Graphics3d Object, Graphics3d Object, Graphics3d Object] - >>> from sage.all import * >>> # needs sage.plot >>> g = sphere() >>> g.all [Graphics3d Object] >>> from sage.manifolds.utilities import set_axes_labels >>> ga = set_axes_labels(g, 'X', 'Y', 'Z', color='red') >>> ga.all # the 3D frame has now axes labels [Graphics3d Object, Graphics3d Object, Graphics3d Object, Graphics3d Object] 
- sage.manifolds.utilities.simplify_abs_trig(expr)[source]¶
- Simplify - abs(sin(...))and- abs(cos(...))in symbolic expressions.- EXAMPLES: - sage: M = Manifold(3, 'M', structure='topological') sage: X.<x,y,z> = M.chart(r'x y:(0,pi) z:(-pi/3,0)') sage: X.coord_range() x: (-oo, +oo); y: (0, pi); z: (-1/3*pi, 0) - >>> from sage.all import * >>> M = Manifold(Integer(3), 'M', structure='topological') >>> X = M.chart(r'x y:(0,pi) z:(-pi/3,0)', names=('x', 'y', 'z',)); (x, y, z,) = X._first_ngens(3) >>> X.coord_range() x: (-oo, +oo); y: (0, pi); z: (-1/3*pi, 0) - Since \(x\) spans all \(\RR\), no simplification of - abs(sin(x))occurs, while- abs(sin(y))and- abs(sin(3*z))are correctly simplified, given that \(y \in (0,\pi)\) and \(z \in (-\pi/3,0)\):- sage: from sage.manifolds.utilities import simplify_abs_trig sage: simplify_abs_trig( abs(sin(x)) + abs(sin(y)) + abs(sin(3*z)) ) abs(sin(x)) + sin(y) + sin(-3*z) - >>> from sage.all import * >>> from sage.manifolds.utilities import simplify_abs_trig >>> simplify_abs_trig( abs(sin(x)) + abs(sin(y)) + abs(sin(Integer(3)*z)) ) abs(sin(x)) + sin(y) + sin(-3*z) - Note that neither - simplify_trig()nor- simplify_full()works in this case:- sage: s = abs(sin(x)) + abs(sin(y)) + abs(sin(3*z)) sage: s.simplify_trig() abs(4*cos(-z)^2 - 1)*abs(sin(-z)) + abs(sin(x)) + abs(sin(y)) sage: s.simplify_full() abs(4*cos(-z)^2 - 1)*abs(sin(-z)) + abs(sin(x)) + abs(sin(y)) - >>> from sage.all import * >>> s = abs(sin(x)) + abs(sin(y)) + abs(sin(Integer(3)*z)) >>> s.simplify_trig() abs(4*cos(-z)^2 - 1)*abs(sin(-z)) + abs(sin(x)) + abs(sin(y)) >>> s.simplify_full() abs(4*cos(-z)^2 - 1)*abs(sin(-z)) + abs(sin(x)) + abs(sin(y)) - despite the following assumptions hold: - sage: assumptions() [x is real, y is real, y > 0, y < pi, z is real, z > -1/3*pi, z < 0] - >>> from sage.all import * >>> assumptions() [x is real, y is real, y > 0, y < pi, z is real, z > -1/3*pi, z < 0] - Additional checks are: - sage: simplify_abs_trig( abs(sin(y/2)) ) # shall simplify sin(1/2*y) sage: simplify_abs_trig( abs(sin(2*y)) ) # must not simplify abs(sin(2*y)) sage: simplify_abs_trig( abs(sin(z/2)) ) # shall simplify sin(-1/2*z) sage: simplify_abs_trig( abs(sin(4*z)) ) # must not simplify abs(sin(-4*z)) - >>> from sage.all import * >>> simplify_abs_trig( abs(sin(y/Integer(2))) ) # shall simplify sin(1/2*y) >>> simplify_abs_trig( abs(sin(Integer(2)*y)) ) # must not simplify abs(sin(2*y)) >>> simplify_abs_trig( abs(sin(z/Integer(2))) ) # shall simplify sin(-1/2*z) >>> simplify_abs_trig( abs(sin(Integer(4)*z)) ) # must not simplify abs(sin(-4*z)) - Simplification of - abs(cos(...)):- sage: forget() sage: M = Manifold(3, 'M', structure='topological') sage: X.<x,y,z> = M.chart(r'x y:(0,pi/2) z:(pi/4,3*pi/4)') sage: X.coord_range() x: (-oo, +oo); y: (0, 1/2*pi); z: (1/4*pi, 3/4*pi) sage: simplify_abs_trig( abs(cos(x)) + abs(cos(y)) + abs(cos(2*z)) ) abs(cos(x)) + cos(y) - cos(2*z) - >>> from sage.all import * >>> forget() >>> M = Manifold(Integer(3), 'M', structure='topological') >>> X = M.chart(r'x y:(0,pi/2) z:(pi/4,3*pi/4)', names=('x', 'y', 'z',)); (x, y, z,) = X._first_ngens(3) >>> X.coord_range() x: (-oo, +oo); y: (0, 1/2*pi); z: (1/4*pi, 3/4*pi) >>> simplify_abs_trig( abs(cos(x)) + abs(cos(y)) + abs(cos(Integer(2)*z)) ) abs(cos(x)) + cos(y) - cos(2*z) - Additional tests: - sage: simplify_abs_trig(abs(cos(y-pi/2))) # shall simplify cos(-1/2*pi + y) sage: simplify_abs_trig(abs(cos(y+pi/2))) # shall simplify -cos(1/2*pi + y) sage: simplify_abs_trig(abs(cos(y-pi))) # shall simplify -cos(-pi + y) sage: simplify_abs_trig(abs(cos(2*y))) # must not simplify abs(cos(2*y)) sage: simplify_abs_trig(abs(cos(y/2)) * abs(sin(z))) # shall simplify cos(1/2*y)*sin(z) - >>> from sage.all import * >>> simplify_abs_trig(abs(cos(y-pi/Integer(2)))) # shall simplify cos(-1/2*pi + y) >>> simplify_abs_trig(abs(cos(y+pi/Integer(2)))) # shall simplify -cos(1/2*pi + y) >>> simplify_abs_trig(abs(cos(y-pi))) # shall simplify -cos(-pi + y) >>> simplify_abs_trig(abs(cos(Integer(2)*y))) # must not simplify abs(cos(2*y)) >>> simplify_abs_trig(abs(cos(y/Integer(2))) * abs(sin(z))) # shall simplify cos(1/2*y)*sin(z) 
- sage.manifolds.utilities.simplify_chain_generic(expr)[source]¶
- Apply a chain of simplifications to a symbolic expression. - This is the simplification chain used in calculus involving coordinate functions on manifolds over fields different from \(\RR\), as implemented in - ChartFunction.- The chain is formed by the following functions, called successively: - NB: for the time being, this is identical to - simplify_full().- EXAMPLES: - We consider variables that are coordinates of a chart on a complex manifold: - sage: M = Manifold(2, 'M', structure='topological', field='complex') sage: X.<x,y> = M.chart() - >>> from sage.all import * >>> M = Manifold(Integer(2), 'M', structure='topological', field='complex') >>> X = M.chart(names=('x', 'y',)); (x, y,) = X._first_ngens(2) - Then neither - xnor- yis assumed to be real:- sage: assumptions() [] - >>> from sage.all import * >>> assumptions() [] - Accordingly, - simplify_chain_genericdoes not simplify- sqrt(x^2)to- abs(x):- sage: from sage.manifolds.utilities import simplify_chain_generic sage: s = sqrt(x^2) sage: simplify_chain_generic(s) sqrt(x^2) - >>> from sage.all import * >>> from sage.manifolds.utilities import simplify_chain_generic >>> s = sqrt(x**Integer(2)) >>> simplify_chain_generic(s) sqrt(x^2) - This contrasts with the behavior of - simplify_chain_real().- Other simplifications: - sage: s = (x+y)^2 - x^2 -2*x*y - y^2 sage: simplify_chain_generic(s) 0 sage: s = (x^2 - 2*x + 1) / (x^2 -1) sage: simplify_chain_generic(s) (x - 1)/(x + 1) sage: s = cos(2*x) - 2*cos(x)^2 + 1 sage: simplify_chain_generic(s) 0 - >>> from sage.all import * >>> s = (x+y)**Integer(2) - x**Integer(2) -Integer(2)*x*y - y**Integer(2) >>> simplify_chain_generic(s) 0 >>> s = (x**Integer(2) - Integer(2)*x + Integer(1)) / (x**Integer(2) -Integer(1)) >>> simplify_chain_generic(s) (x - 1)/(x + 1) >>> s = cos(Integer(2)*x) - Integer(2)*cos(x)**Integer(2) + Integer(1) >>> simplify_chain_generic(s) 0 
- sage.manifolds.utilities.simplify_chain_generic_sympy(expr)[source]¶
- Apply a chain of simplifications to a sympy expression. - This is the simplification chain used in calculus involving coordinate functions on manifolds over fields different from \(\RR\), as implemented in - ChartFunction.- The chain is formed by the following functions, called successively: - combsimp()
- trigsimp()
- expand()
- simplify()
 - EXAMPLES: - We consider variables that are coordinates of a chart on a complex manifold: - sage: forget() # for doctest only sage: M = Manifold(2, 'M', structure='topological', field='complex', calc_method='sympy') sage: X.<x,y> = M.chart() - >>> from sage.all import * >>> forget() # for doctest only >>> M = Manifold(Integer(2), 'M', structure='topological', field='complex', calc_method='sympy') >>> X = M.chart(names=('x', 'y',)); (x, y,) = X._first_ngens(2) - Then neither - xnor- yis assumed to be real:- sage: assumptions() [] - >>> from sage.all import * >>> assumptions() [] - Accordingly, - simplify_chain_generic_sympydoes not simplify- sqrt(x^2)to- abs(x):- sage: from sage.manifolds.utilities import simplify_chain_generic_sympy sage: s = (sqrt(x^2))._sympy_() sage: simplify_chain_generic_sympy(s) sqrt(x**2) - >>> from sage.all import * >>> from sage.manifolds.utilities import simplify_chain_generic_sympy >>> s = (sqrt(x**Integer(2)))._sympy_() >>> simplify_chain_generic_sympy(s) sqrt(x**2) - This contrasts with the behavior of - simplify_chain_real_sympy().- Other simplifications: - sage: s = ((x+y)^2 - x^2 -2*x*y - y^2)._sympy_() sage: simplify_chain_generic_sympy(s) 0 sage: s = ((x^2 - 2*x + 1) / (x^2 -1))._sympy_() sage: simplify_chain_generic_sympy(s) (x - 1)/(x + 1) sage: s = (cos(2*x) - 2*cos(x)^2 + 1)._sympy_() sage: simplify_chain_generic_sympy(s) 0 - >>> from sage.all import * >>> s = ((x+y)**Integer(2) - x**Integer(2) -Integer(2)*x*y - y**Integer(2))._sympy_() >>> simplify_chain_generic_sympy(s) 0 >>> s = ((x**Integer(2) - Integer(2)*x + Integer(1)) / (x**Integer(2) -Integer(1)))._sympy_() >>> simplify_chain_generic_sympy(s) (x - 1)/(x + 1) >>> s = (cos(Integer(2)*x) - Integer(2)*cos(x)**Integer(2) + Integer(1))._sympy_() >>> simplify_chain_generic_sympy(s) 0 
- sage.manifolds.utilities.simplify_chain_real(expr)[source]¶
- Apply a chain of simplifications to a symbolic expression, assuming the real domain. - This is the simplification chain used in calculus involving coordinate functions on real manifolds, as implemented in - ChartFunction.- The chain is formed by the following functions, called successively: - EXAMPLES: - We consider variables that are coordinates of a chart on a real manifold: - sage: M = Manifold(2, 'M', structure='topological') sage: X.<x,y> = M.chart('x:(0,1) y') - >>> from sage.all import * >>> M = Manifold(Integer(2), 'M', structure='topological') >>> X = M.chart('x:(0,1) y', names=('x', 'y',)); (x, y,) = X._first_ngens(2) - The following assumptions then hold: - sage: assumptions() [x is real, x > 0, x < 1, y is real] - >>> from sage.all import * >>> assumptions() [x is real, x > 0, x < 1, y is real] - and we have: - sage: from sage.manifolds.utilities import simplify_chain_real sage: s = sqrt(y^2) sage: simplify_chain_real(s) abs(y) - >>> from sage.all import * >>> from sage.manifolds.utilities import simplify_chain_real >>> s = sqrt(y**Integer(2)) >>> simplify_chain_real(s) abs(y) - The above result is correct since - yis real. It is obtained by- simplify_real()as well:- sage: s.simplify_real() abs(y) sage: s.simplify_full() abs(y) - >>> from sage.all import * >>> s.simplify_real() abs(y) >>> s.simplify_full() abs(y) - Furthermore, we have: - sage: s = sqrt(x^2-2*x+1) sage: simplify_chain_real(s) -x + 1 - >>> from sage.all import * >>> s = sqrt(x**Integer(2)-Integer(2)*x+Integer(1)) >>> simplify_chain_real(s) -x + 1 - which is correct since \(x \in (0,1)\). On this example, neither - simplify_real()nor- simplify_full(), nor- canonicalize_radical()give satisfactory results:- sage: s.simplify_real() # unsimplified output sqrt(x^2 - 2*x + 1) sage: s.simplify_full() # unsimplified output sqrt(x^2 - 2*x + 1) sage: s.canonicalize_radical() # wrong output since x in (0,1) x - 1 - >>> from sage.all import * >>> s.simplify_real() # unsimplified output sqrt(x^2 - 2*x + 1) >>> s.simplify_full() # unsimplified output sqrt(x^2 - 2*x + 1) >>> s.canonicalize_radical() # wrong output since x in (0,1) x - 1 - Other simplifications: - sage: s = abs(sin(pi*x)) sage: simplify_chain_real(s) # correct output since x in (0,1) sin(pi*x) sage: s.simplify_real() # unsimplified output abs(sin(pi*x)) sage: s.simplify_full() # unsimplified output abs(sin(pi*x)) - >>> from sage.all import * >>> s = abs(sin(pi*x)) >>> simplify_chain_real(s) # correct output since x in (0,1) sin(pi*x) >>> s.simplify_real() # unsimplified output abs(sin(pi*x)) >>> s.simplify_full() # unsimplified output abs(sin(pi*x)) - sage: s = cos(y)^2 + sin(y)^2 sage: simplify_chain_real(s) 1 sage: s.simplify_real() # unsimplified output cos(y)^2 + sin(y)^2 sage: s.simplify_full() # OK 1 - >>> from sage.all import * >>> s = cos(y)**Integer(2) + sin(y)**Integer(2) >>> simplify_chain_real(s) 1 >>> s.simplify_real() # unsimplified output cos(y)^2 + sin(y)^2 >>> s.simplify_full() # OK 1 
- sage.manifolds.utilities.simplify_chain_real_sympy(expr)[source]¶
- Apply a chain of simplifications to a sympy expression, assuming the real domain. - This is the simplification chain used in calculus involving coordinate functions on real manifolds, as implemented in - ChartFunction.- The chain is formed by the following functions, called successively: - combsimp()
- trigsimp()
- expand()
- simplify()
 - EXAMPLES: - We consider variables that are coordinates of a chart on a real manifold: - sage: forget() # for doctest only sage: M = Manifold(2, 'M', structure='topological',calc_method='sympy') sage: X.<x,y> = M.chart('x:(0,1) y') - >>> from sage.all import * >>> forget() # for doctest only >>> M = Manifold(Integer(2), 'M', structure='topological',calc_method='sympy') >>> X = M.chart('x:(0,1) y', names=('x', 'y',)); (x, y,) = X._first_ngens(2) - The following assumptions then hold: - sage: assumptions() [x is real, x > 0, x < 1, y is real] - >>> from sage.all import * >>> assumptions() [x is real, x > 0, x < 1, y is real] - and we have: - sage: from sage.manifolds.utilities import simplify_chain_real_sympy sage: s = (sqrt(y^2))._sympy_() sage: simplify_chain_real_sympy(s) Abs(y) - >>> from sage.all import * >>> from sage.manifolds.utilities import simplify_chain_real_sympy >>> s = (sqrt(y**Integer(2)))._sympy_() >>> simplify_chain_real_sympy(s) Abs(y) - Furthermore, we have: - sage: s = (sqrt(x^2-2*x+1))._sympy_() sage: simplify_chain_real_sympy(s) 1 - x - >>> from sage.all import * >>> s = (sqrt(x**Integer(2)-Integer(2)*x+Integer(1)))._sympy_() >>> simplify_chain_real_sympy(s) 1 - x - Other simplifications: - sage: s = (abs(sin(pi*x)))._sympy_() sage: simplify_chain_real_sympy(s) # correct output since x in (0,1) sin(pi*x) - >>> from sage.all import * >>> s = (abs(sin(pi*x)))._sympy_() >>> simplify_chain_real_sympy(s) # correct output since x in (0,1) sin(pi*x) - sage: s = (cos(y)^2 + sin(y)^2)._sympy_() sage: simplify_chain_real_sympy(s) 1 - >>> from sage.all import * >>> s = (cos(y)**Integer(2) + sin(y)**Integer(2))._sympy_() >>> simplify_chain_real_sympy(s) 1 
- sage.manifolds.utilities.simplify_sqrt_real(expr)[source]¶
- Simplify - sqrtin symbolic expressions in the real domain.- EXAMPLES: - Simplifications of basic expressions: - sage: from sage.manifolds.utilities import simplify_sqrt_real sage: simplify_sqrt_real( sqrt(x^2) ) abs(x) sage: assume(x<0) sage: simplify_sqrt_real( sqrt(x^2) ) -x sage: simplify_sqrt_real( sqrt(x^2-2*x+1) ) -x + 1 sage: simplify_sqrt_real( sqrt(x^2) + sqrt(x^2-2*x+1) ) -2*x + 1 - >>> from sage.all import * >>> from sage.manifolds.utilities import simplify_sqrt_real >>> simplify_sqrt_real( sqrt(x**Integer(2)) ) abs(x) >>> assume(x<Integer(0)) >>> simplify_sqrt_real( sqrt(x**Integer(2)) ) -x >>> simplify_sqrt_real( sqrt(x**Integer(2)-Integer(2)*x+Integer(1)) ) -x + 1 >>> simplify_sqrt_real( sqrt(x**Integer(2)) + sqrt(x**Integer(2)-Integer(2)*x+Integer(1)) ) -2*x + 1 - This improves over - canonicalize_radical(), which yields incorrect results when- x < 0:- sage: forget() # removes the assumption x<0 sage: sqrt(x^2).canonicalize_radical() x sage: assume(x<0) sage: sqrt(x^2).canonicalize_radical() -x sage: sqrt(x^2-2*x+1).canonicalize_radical() # wrong output x - 1 sage: ( sqrt(x^2) + sqrt(x^2-2*x+1) ).canonicalize_radical() # wrong output -1 - >>> from sage.all import * >>> forget() # removes the assumption x<0 >>> sqrt(x**Integer(2)).canonicalize_radical() x >>> assume(x<Integer(0)) >>> sqrt(x**Integer(2)).canonicalize_radical() -x >>> sqrt(x**Integer(2)-Integer(2)*x+Integer(1)).canonicalize_radical() # wrong output x - 1 >>> ( sqrt(x**Integer(2)) + sqrt(x**Integer(2)-Integer(2)*x+Integer(1)) ).canonicalize_radical() # wrong output -1 - Simplification of nested - sqrt’s:- sage: forget() # removes the assumption x<0 sage: simplify_sqrt_real( sqrt(1 + sqrt(x^2)) ) sqrt(abs(x) + 1) sage: assume(x<0) sage: simplify_sqrt_real( sqrt(1 + sqrt(x^2)) ) sqrt(-x + 1) sage: simplify_sqrt_real( sqrt(x^2 + sqrt(4*x^2) + 1) ) -x + 1 - >>> from sage.all import * >>> forget() # removes the assumption x<0 >>> simplify_sqrt_real( sqrt(Integer(1) + sqrt(x**Integer(2))) ) sqrt(abs(x) + 1) >>> assume(x<Integer(0)) >>> simplify_sqrt_real( sqrt(Integer(1) + sqrt(x**Integer(2))) ) sqrt(-x + 1) >>> simplify_sqrt_real( sqrt(x**Integer(2) + sqrt(Integer(4)*x**Integer(2)) + Integer(1)) ) -x + 1 - Again, - canonicalize_radical()fails on the last one:- sage: (sqrt(x^2 + sqrt(4*x^2) + 1)).canonicalize_radical() x - 1 - >>> from sage.all import * >>> (sqrt(x**Integer(2) + sqrt(Integer(4)*x**Integer(2)) + Integer(1))).canonicalize_radical() x - 1 
- sage.manifolds.utilities.xder(form)[source]¶
- Exterior derivative of a differential form. - INPUT: - form– a differential form; this must an instance of either- DiffScalarFieldfor a 0-form (scalar field)
- DiffFormParalfor a \(p\)-form (\(p\geq 1\)) on a parallelizable manifold
- DiffFormfor a a \(p\)-form (\(p\geq 1\)) on a non-parallelizable manifold
 
 - OUTPUT: - the \((p+1)\)-form that is the exterior derivative of - form
 - EXAMPLES: - Exterior derivative of a scalar field (0-form): - sage: from sage.manifolds.utilities import exterior_derivative sage: M = Manifold(3, 'M') sage: X.<x,y,z> = M.chart() sage: f = M.scalar_field({X: x+y^2+z^3}, name='f') sage: df = exterior_derivative(f); df 1-form df on the 3-dimensional differentiable manifold M sage: df.display() df = dx + 2*y dy + 3*z^2 dz - >>> from sage.all import * >>> from sage.manifolds.utilities import exterior_derivative >>> M = Manifold(Integer(3), 'M') >>> X = M.chart(names=('x', 'y', 'z',)); (x, y, z,) = X._first_ngens(3) >>> f = M.scalar_field({X: x+y**Integer(2)+z**Integer(3)}, name='f') >>> df = exterior_derivative(f); df 1-form df on the 3-dimensional differentiable manifold M >>> df.display() df = dx + 2*y dy + 3*z^2 dz - An alias is - xder:- sage: from sage.manifolds.utilities import xder sage: df == xder(f) True - >>> from sage.all import * >>> from sage.manifolds.utilities import xder >>> df == xder(f) True - Exterior derivative of a 1-form: - sage: a = M.one_form(name='a') sage: a[:] = [x+y*z, x-y*z, x*y*z] sage: da = xder(a); da 2-form da on the 3-dimensional differentiable manifold M sage: da.display() da = (-z + 1) dx∧dy + (y*z - y) dx∧dz + (x*z + y) dy∧dz sage: dda = xder(da); dda 3-form dda on the 3-dimensional differentiable manifold M sage: dda.display() dda = 0 - >>> from sage.all import * >>> a = M.one_form(name='a') >>> a[:] = [x+y*z, x-y*z, x*y*z] >>> da = xder(a); da 2-form da on the 3-dimensional differentiable manifold M >>> da.display() da = (-z + 1) dx∧dy + (y*z - y) dx∧dz + (x*z + y) dy∧dz >>> dda = xder(da); dda 3-form dda on the 3-dimensional differentiable manifold M >>> dda.display() dda = 0