diff --git a/src/sage/manifolds/calculus_method.py b/src/sage/manifolds/calculus_method.py index 303dde6cd13..ddbad8a11ef 100644 --- a/src/sage/manifolds/calculus_method.py +++ b/src/sage/manifolds/calculus_method.py @@ -27,7 +27,12 @@ simplify_chain_real_sympy, simplify_chain_generic_sympy,) from sage.misc.latex import latex -import sympy + +try: + import sympy + from sympy import latex as sympy_latex +except ImportError: + sympy_latex = None # Conversion functions @@ -202,7 +207,7 @@ def __init__(self, current=None, base_field_type='real'): self._simplify_dict['SR'] = simplify_chain_generic # The default simplifying functions are saved: self._simplify_dict_default = self._simplify_dict.copy() - self._latex_dict = {'sympy': sympy.latex, 'SR': latex} + self._latex_dict = {'sympy': sympy_latex, 'SR': latex} def simplify(self, expression, method=None): r""" diff --git a/src/sage/manifolds/chart.py b/src/sage/manifolds/chart.py index 0705d4ecd88..e625299a6cc 100644 --- a/src/sage/manifolds/chart.py +++ b/src/sage/manifolds/chart.py @@ -1165,6 +1165,7 @@ def preimage(self, codomain_subset, name=None, latex_name=None): Pulling back a polytope under a chart:: + sage: # needs sage.geometry.polyhedron sage: P = Polyhedron(vertices=[[0, 0], [1, 2], [2, 1]]); P A 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 3 vertices sage: McP = c_cart.preimage(P); McP @@ -1176,6 +1177,7 @@ def preimage(self, codomain_subset, name=None, latex_name=None): Pulling back the interior of a polytope under a chart:: + sage: # needs sage.geometry.polyhedron sage: int_P = P.interior(); int_P Relative interior of a 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 3 vertices @@ -1384,6 +1386,7 @@ def zero_function(self): Zero function on a p-adic manifold:: + sage: # needs sage.rings.padics sage: M = Manifold(2, 'M', structure='topological', field=Qp(5)); M 2-dimensional topological manifold M over the 5-adic Field with capped relative precision 20 @@ -1438,6 +1441,7 @@ def one_function(self): One function on a p-adic manifold:: + sage: # needs sage.rings.padics sage: M = Manifold(2, 'M', structure='topological', field=Qp(5)); M 2-dimensional topological manifold M over the 5-adic Field with capped relative precision 20 @@ -2754,10 +2758,9 @@ def plot(self, chart=None, ambient_coords=None, mapping=None, A 2-dimensional chart plotted in terms of itself results in a rectangular grid:: - sage: R2 = Manifold(2, 'R^2', structure='topological') # the Euclidean plane - sage: c_cart. = R2.chart() # Cartesian coordinates - sage: g = c_cart.plot() # equivalent to c_cart.plot(c_cart) - sage: g + sage: R2 = Manifold(2, 'R^2', structure='topological') # the Euclidean plane + sage: c_cart. = R2.chart() # Cartesian coordinates + sage: g = c_cart.plot(); g # equivalent to c_cart.plot(c_cart) # needs sage.plot Graphics object consisting of 18 graphics primitives .. PLOT:: @@ -2770,11 +2773,10 @@ def plot(self, chart=None, ambient_coords=None, mapping=None, Grid of polar coordinates in terms of Cartesian coordinates in the Euclidean plane:: - sage: U = R2.open_subset('U', coord_def={c_cart: (y!=0, x<0)}) # the complement of the segment y=0 and x>0 - sage: c_pol. = U.chart(r'r:(0,+oo) ph:(0,2*pi):\phi') # polar coordinates on U + sage: U = R2.open_subset('U', coord_def={c_cart: (y!=0, x<0)}) # the complement of the segment y=0 and x>0 + sage: c_pol. = U.chart(r'r:(0,+oo) ph:(0,2*pi):\phi') # polar coordinates on U sage: pol_to_cart = c_pol.transition_map(c_cart, [r*cos(ph), r*sin(ph)]) - sage: g = c_pol.plot(c_cart) - sage: g + sage: g = c_pol.plot(c_cart); g # needs sage.plot Graphics object consisting of 18 graphics primitives .. PLOT:: @@ -2789,7 +2791,7 @@ def plot(self, chart=None, ambient_coords=None, mapping=None, Call with non-default values:: - sage: g = c_pol.plot(c_cart, ranges={ph:(pi/4,pi)}, + sage: g = c_pol.plot(c_cart, ranges={ph:(pi/4,pi)}, # needs sage.plot ....: number_values={r:7, ph:17}, ....: color={r:'red', ph:'green'}, ....: style={r:'-', ph:'--'}) @@ -2807,7 +2809,8 @@ def plot(self, chart=None, ambient_coords=None, mapping=None, A single coordinate line can be drawn:: - sage: g = c_pol.plot(c_cart, fixed_coords={r: 2}) # draw a circle of radius r=2 + sage: g = c_pol.plot(c_cart, # draw a circle of radius r=2 # needs sage.plot + ....: fixed_coords={r: 2}) .. PLOT:: @@ -2821,7 +2824,8 @@ def plot(self, chart=None, ambient_coords=None, mapping=None, :: - sage: g = c_pol.plot(c_cart, fixed_coords={ph: pi/4}) # draw a segment at phi=pi/4 + sage: g = c_pol.plot(c_cart, # draw a segment at phi=pi/4 # needs sage.plot + ....: fixed_coords={ph: pi/4}) .. PLOT:: @@ -2838,24 +2842,23 @@ def plot(self, chart=None, ambient_coords=None, mapping=None, argument ``mapping``): 3D plot of the stereographic charts on the 2-sphere:: - sage: S2 = Manifold(2, 'S^2', structure='topological') # the 2-sphere - sage: U = S2.open_subset('U') ; V = S2.open_subset('V') # complement of the North and South pole, respectively + sage: S2 = Manifold(2, 'S^2', structure='topological') # the 2-sphere + sage: U = S2.open_subset('U'); V = S2.open_subset('V') # complement of the North and South pole, respectively sage: S2.declare_union(U,V) - sage: c_xy. = U.chart() # stereographic coordinates from the North pole - sage: c_uv. = V.chart() # stereographic coordinates from the South pole + sage: c_xy. = U.chart() # stereographic coordinates from the North pole + sage: c_uv. = V.chart() # stereographic coordinates from the South pole sage: xy_to_uv = c_xy.transition_map(c_uv, (x/(x^2+y^2), y/(x^2+y^2)), ....: intersection_name='W', restrictions1= x^2+y^2!=0, ....: restrictions2= u^2+v^2!=0) sage: uv_to_xy = xy_to_uv.inverse() - sage: R3 = Manifold(3, 'R^3', structure='topological') # the Euclidean space R^3 + sage: R3 = Manifold(3, 'R^3', structure='topological') # the Euclidean space R^3 sage: c_cart. = R3.chart() # Cartesian coordinates on R^3 sage: Phi = S2.continuous_map(R3, {(c_xy, c_cart): [2*x/(1+x^2+y^2), ....: 2*y/(1+x^2+y^2), (x^2+y^2-1)/(1+x^2+y^2)], ....: (c_uv, c_cart): [2*u/(1+u^2+v^2), ....: 2*v/(1+u^2+v^2), (1-u^2-v^2)/(1+u^2+v^2)]}, - ....: name='Phi', latex_name=r'\Phi') # Embedding of S^2 in R^3 - sage: g = c_xy.plot(c_cart, mapping=Phi) - sage: g + ....: name='Phi', latex_name=r'\Phi') # Embedding of S^2 in R^3 + sage: g = c_xy.plot(c_cart, mapping=Phi); g # needs sage.plot Graphics3d Object .. PLOT:: @@ -2885,12 +2888,12 @@ def plot(self, chart=None, ambient_coords=None, mapping=None, The same plot without the ``(X,Y,Z)`` axes labels:: - sage: g = c_xy.plot(c_cart, mapping=Phi, label_axes=False) + sage: g = c_xy.plot(c_cart, mapping=Phi, label_axes=False) # needs sage.plot The North and South stereographic charts on the same plot:: - sage: g2 = c_uv.plot(c_cart, mapping=Phi, color='green') - sage: g + g2 + sage: g2 = c_uv.plot(c_cart, mapping=Phi, color='green') # needs sage.plot + sage: g + g2 # needs sage.plot Graphics3d Object .. PLOT:: @@ -2915,16 +2918,17 @@ def plot(self, chart=None, ambient_coords=None, mapping=None, g2 = c_uv.plot(c_cart, mapping=Phi, color='green') sphinx_plot(g+g2) - South stereographic chart drawned in terms of the North one (we split + South stereographic chart drawn in terms of the North one (we split the plot in four parts to avoid the singularity at `(u,v)=(0,0)`):: + sage: # long time, needs sage.plot sage: W = U.intersection(V) # the subset common to both charts sage: c_uvW = c_uv.restrict(W) # chart (W,(u,v)) - sage: gSN1 = c_uvW.plot(c_xy, ranges={u:[-6.,-0.02], v:[-6.,-0.02]}) # long time - sage: gSN2 = c_uvW.plot(c_xy, ranges={u:[-6.,-0.02], v:[0.02,6.]}) # long time - sage: gSN3 = c_uvW.plot(c_xy, ranges={u:[0.02,6.], v:[-6.,-0.02]}) # long time - sage: gSN4 = c_uvW.plot(c_xy, ranges={u:[0.02,6.], v:[0.02,6.]}) # long time - sage: show(gSN1+gSN2+gSN3+gSN4, xmin=-1.5, xmax=1.5, ymin=-1.5, ymax=1.5) # long time + sage: gSN1 = c_uvW.plot(c_xy, ranges={u:[-6.,-0.02], v:[-6.,-0.02]}) + sage: gSN2 = c_uvW.plot(c_xy, ranges={u:[-6.,-0.02], v:[0.02,6.]}) + sage: gSN3 = c_uvW.plot(c_xy, ranges={u:[0.02,6.], v:[-6.,-0.02]}) + sage: gSN4 = c_uvW.plot(c_xy, ranges={u:[0.02,6.], v:[0.02,6.]}) + sage: show(gSN1+gSN2+gSN3+gSN4, xmin=-1.5, xmax=1.5, ymin=-1.5, ymax=1.5) .. PLOT:: @@ -2947,9 +2951,12 @@ def plot(self, chart=None, ambient_coords=None, mapping=None, The coordinate line `u = 1` (red) and the coordinate line `v = 1` (green) on the same plot:: - sage: gu1 = c_uvW.plot(c_xy, fixed_coords={u: 1}, max_range=20, plot_points=300) # long time - sage: gv1 = c_uvW.plot(c_xy, fixed_coords={v: 1}, max_range=20, plot_points=300, color='green') # long time - sage: gu1 + gv1 # long time + sage: # long time, needs sage.plot + sage: gu1 = c_uvW.plot(c_xy, fixed_coords={u: 1}, max_range=20, + ....: plot_points=300) + sage: gv1 = c_uvW.plot(c_xy, fixed_coords={v: 1}, max_range=20, + ....: plot_points=300, color='green') + sage: gu1 + gv1 Graphics object consisting of 2 graphics primitives .. PLOT:: @@ -2975,8 +2982,9 @@ def plot(self, chart=None, ambient_coords=None, mapping=None, A 3-dimensional chart plotted in terms of itself results in a 3D rectangular grid:: - sage: g = c_cart.plot() # equivalent to c_cart.plot(c_cart) # long time - sage: g # long time + sage: # long time, needs sage.plot + sage: g = c_cart.plot() # equivalent to c_cart.plot(c_cart) + sage: g Graphics3d Object .. PLOT:: @@ -2989,10 +2997,11 @@ def plot(self, chart=None, ambient_coords=None, mapping=None, performed for at most 3 coordinates, which must be specified via the argument ``ambient_coords``):: + sage: # needs sage.plot sage: M = Manifold(4, 'M', structure='topological') sage: X. = M.chart() - sage: g = X.plot(ambient_coords=(t,x,y)) # the coordinate z is not depicted # long time - sage: g # long time + sage: g = X.plot(ambient_coords=(t,x,y)) # the coordinate z is not depicted # long time + sage: g # long time Graphics3d Object .. PLOT:: @@ -3004,7 +3013,8 @@ def plot(self, chart=None, ambient_coords=None, mapping=None, :: - sage: g = X.plot(ambient_coords=(t,y)) # the coordinates x and z are not depicted + sage: # needs sage.plot + sage: g = X.plot(ambient_coords=(t,y)) # the coordinates x and z are not depicted sage: g Graphics object consisting of 18 graphics primitives diff --git a/src/sage/manifolds/chart_func.py b/src/sage/manifolds/chart_func.py index d7104cb7f0b..6363ed61841 100644 --- a/src/sage/manifolds/chart_func.py +++ b/src/sage/manifolds/chart_func.py @@ -40,9 +40,14 @@ from sage.categories.commutative_algebras import CommutativeAlgebras from sage.manifolds.utilities import ExpressionNice from sage.misc.cachefunc import cached_method +from sage.misc.lazy_import import lazy_import from sage.symbolic.ring import SR from sage.structure.mutability import Mutability -import sympy + +try: + import sympy +except ImportError: + pass class ChartFunction(AlgebraElement, ModuleElementWithMutability): diff --git a/src/sage/manifolds/differentiable/characteristic_cohomology_class.py b/src/sage/manifolds/differentiable/characteristic_cohomology_class.py index 7289f67b913..91ebbf00ccc 100644 --- a/src/sage/manifolds/differentiable/characteristic_cohomology_class.py +++ b/src/sage/manifolds/differentiable/characteristic_cohomology_class.py @@ -260,10 +260,11 @@ Let us check whether this form represents the Euler class correctly:: - sage: expr = e_class_form[2][[1,2]].expr() # long time - sage: expr = integrate(expr, x, -infinity, infinity) # long time - sage: expr = expr.simplify_full() # long time - sage: integrate(expr, y, -infinity, infinity) # long time + sage: # long time + sage: expr = e_class_form[2][[1,2]].expr() + sage: expr = integrate(expr, x, -infinity, infinity) + sage: expr = expr.simplify_full() + sage: integrate(expr, y, -infinity, infinity) 2 As we can see, the integral coincides with the Euler characteristic of `S^2` so diff --git a/src/sage/manifolds/differentiable/curve.py b/src/sage/manifolds/differentiable/curve.py index fd77c39dfc4..7ea264565ae 100644 --- a/src/sage/manifolds/differentiable/curve.py +++ b/src/sage/manifolds/differentiable/curve.py @@ -94,7 +94,7 @@ class DifferentiableCurve(DiffMap): A graphical view of the curve is provided by the method :meth:`plot`:: - sage: c.plot(aspect_ratio=1) + sage: c.plot(aspect_ratio=1) # needs sage.plot Graphics object consisting of 1 graphics primitive .. PLOT:: diff --git a/src/sage/manifolds/differentiable/examples/euclidean.py b/src/sage/manifolds/differentiable/examples/euclidean.py index 97e3aa3d875..eb96b6da587 100644 --- a/src/sage/manifolds/differentiable/examples/euclidean.py +++ b/src/sage/manifolds/differentiable/examples/euclidean.py @@ -1879,14 +1879,15 @@ def _transition_spherical_cartesian(self): Tests of the change-of-frame formulas:: - sage: spher = E.spherical_coordinates() # long time - sage: spher_f = E.spherical_frame() # long time - sage: cart_f = E.cartesian_frame() # long time - sage: E.change_of_frame(cart_f, spher_f)[:,spher] # long time + sage: # long time + sage: spher = E.spherical_coordinates() + sage: spher_f = E.spherical_frame() + sage: cart_f = E.cartesian_frame() + sage: E.change_of_frame(cart_f, spher_f)[:,spher] [cos(ph)*sin(th) cos(ph)*cos(th) -sin(ph)] [sin(ph)*sin(th) cos(th)*sin(ph) cos(ph)] [ cos(th) -sin(th) 0] - sage: E.change_of_frame(spher_f, cart_f)[:,spher] # long time + sage: E.change_of_frame(spher_f, cart_f)[:,spher] [cos(ph)*sin(th) sin(ph)*sin(th) cos(th)] [cos(ph)*cos(th) cos(th)*sin(ph) -sin(th)] [ -sin(ph) cos(ph) 0] @@ -1958,14 +1959,15 @@ def _transition_cylindrical_cartesian(self): Tests of the change-of-frame formulas:: - sage: cylind = E.cylindrical_coordinates() # long time - sage: cylind_f = E.cylindrical_frame() # long time - sage: cart_f= E.cartesian_frame() # long time - sage: E.change_of_frame(cart_f, cylind_f)[:,cylind] # long time + sage: # long time + sage: cylind = E.cylindrical_coordinates() + sage: cylind_f = E.cylindrical_frame() + sage: cart_f= E.cartesian_frame() + sage: E.change_of_frame(cart_f, cylind_f)[:,cylind] [ cos(ph) -sin(ph) 0] [ sin(ph) cos(ph) 0] [ 0 0 1] - sage: E.change_of_frame(cylind_f, cart_f)[:,cylind] # long time + sage: E.change_of_frame(cylind_f, cart_f)[:,cylind] [ cos(ph) sin(ph) 0] [-sin(ph) cos(ph) 0] [ 0 0 1] @@ -2035,14 +2037,15 @@ def _transition_spherical_cylindrical(self): Tests of the change-of-frame formulas:: - sage: spher = E.spherical_coordinates() # long time - sage: spher_f = E.spherical_frame() # long time - sage: cylind_f = E.cylindrical_frame() # long time - sage: E.change_of_frame(cylind_f, spher_f)[:, spher] # long time + sage: # long time + sage: spher = E.spherical_coordinates() + sage: spher_f = E.spherical_frame() + sage: cylind_f = E.cylindrical_frame() + sage: E.change_of_frame(cylind_f, spher_f)[:, spher] [ sin(th) cos(th) 0] [ 0 0 1] [ cos(th) -sin(th) 0] - sage: E.change_of_frame(spher_f, cylind_f)[:, spher] # long time + sage: E.change_of_frame(spher_f, cylind_f)[:, spher] [ sin(th) 0 cos(th)] [ cos(th) 0 -sin(th)] [ 0 1 0] diff --git a/src/sage/manifolds/differentiable/integrated_curve.py b/src/sage/manifolds/differentiable/integrated_curve.py index 0d01a9afd70..fe2a6dcb3cc 100644 --- a/src/sage/manifolds/differentiable/integrated_curve.py +++ b/src/sage/manifolds/differentiable/integrated_curve.py @@ -41,11 +41,13 @@ Numerically integrate the geodesic (see :meth:`~IntegratedCurve.solve` for all possible options, including the choice of the numerical algorithm):: - sage: sol = c.solve() + sage: sol = c.solve() # needs scipy Plot the geodesic after interpolating the solution ``sol``:: sage: interp = c.interpolate() + + sage: # needs sage.plot sage: graph = c.plot_integrated() sage: p_plot = p.plot(size=30, label_offset=-0.07, fontsize=20) sage: v_plot = v.plot(label_offset=0.05, fontsize=20) @@ -116,12 +118,15 @@ from sage.calculus.interpolation import Spline from sage.misc.decorators import options from sage.misc.functional import numerical_approx +from sage.misc.lazy_import import lazy_import from sage.arith.srange import srange from sage.ext.fast_callable import fast_callable from sage.symbolic.ring import SR -from scipy.integrate import ode from random import shuffle +lazy_import('scipy.integrate', 'ode') + + class IntegratedCurve(DifferentiableCurve): r""" Given a chart with coordinates denoted `(x_{1}, \ldots, x_{n})`, @@ -227,7 +232,7 @@ class IntegratedCurve(DifferentiableCurve): Generate a solution of the system and an interpolation of this solution:: - sage: sol = c.solve(step=0.2, + sage: sol = c.solve(step=0.2, # needs scipy ....: parameters_values={B_0:1, m:1, q:1, L:10, T:1}, ....: solution_key='carac time 1', verbose=True) Performing numerical integration with method 'odeint'... @@ -239,7 +244,7 @@ class IntegratedCurve(DifferentiableCurve): The resulting list of points was associated with the key 'carac time 1' (if this key already referred to a former numerical solution, such a solution was erased). - sage: interp = c.interpolate(solution_key='carac time 1', + sage: interp = c.interpolate(solution_key='carac time 1', # needs scipy ....: interpolation_key='interp 1', verbose=True) Performing cubic spline interpolation by default... Interpolation completed and associated with the key 'interp 1' @@ -249,6 +254,7 @@ class IntegratedCurve(DifferentiableCurve): Such an interpolation is required to evaluate the curve and the vector tangent to the curve for any value of the curve parameter:: + sage: # needs scipy sage: p = c(1.9, verbose=True) Evaluating point coordinates from the interpolation associated with the key 'interp 1' by default... @@ -268,7 +274,7 @@ class IntegratedCurve(DifferentiableCurve): Plotting a numerical solution (with or without its tangent vector field) also requires the solution to be interpolated at least once:: - sage: c_plot_2d_1 = c.plot_integrated(ambient_coords=[x1, x2], + sage: c_plot_2d_1 = c.plot_integrated(ambient_coords=[x1, x2], # needs scipy ....: interpolation_key='interp 1', thickness=2.5, ....: display_tangent=True, plot_points=200, ....: plot_points_tangent=10, scale=0.5, @@ -277,7 +283,7 @@ class IntegratedCurve(DifferentiableCurve): A tiny final offset equal to 0.000251256281407035 was introduced for the last point in order to safely compute it from the interpolation. - sage: c_plot_2d_1 + sage: c_plot_2d_1 # needs scipy sage.plot Graphics object consisting of 11 graphics primitives .. PLOT:: @@ -307,22 +313,23 @@ class IntegratedCurve(DifferentiableCurve): An instance of :class:`IntegratedCurve` may store several numerical solutions and interpolations:: + sage: # needs scipy sage: sol = c.solve(step=0.2, ....: parameters_values={B_0:1, m:1, q:1, L:10, T:100}, ....: solution_key='carac time 100') sage: interp = c.interpolate(solution_key='carac time 100', ....: interpolation_key='interp 100') - sage: c_plot_3d_100 = c.plot_integrated(interpolation_key='interp 100', + sage: c_plot_3d_100 = c.plot_integrated(interpolation_key='interp 100', # needs sage.plot ....: thickness=2.5, display_tangent=True, ....: plot_points=200, plot_points_tangent=10, ....: scale=0.5, color='green', ....: color_tangent='orange') - sage: c_plot_3d_1 = c.plot_integrated(interpolation_key='interp 1', + sage: c_plot_3d_1 = c.plot_integrated(interpolation_key='interp 1', # needs sage.plot ....: thickness=2.5, display_tangent=True, ....: plot_points=200, plot_points_tangent=10, ....: scale=0.5, color='blue', ....: color_tangent='red') - sage: c_plot_3d_1 + c_plot_3d_100 + sage: c_plot_3d_1 + c_plot_3d_100 # needs sage.plot Graphics3d Object .. PLOT:: @@ -1001,7 +1008,7 @@ def solve(self, step=None, method='odeint', solution_key=None, sage: Tp = M.tangent_space(p) sage: v = Tp((1,0,1)) sage: c = M.integrated_curve(eqns, D, (t,0,5), v, name='c') - sage: sol = c.solve(parameters_values={B_0:1, m:1, q:1, L:10, T:1}, + sage: sol = c.solve(parameters_values={B_0:1, m:1, q:1, L:10, T:1}, # needs scipy ....: verbose=True) Performing numerical integration with method 'odeint'... Resulting list of points will be associated with the key @@ -1017,38 +1024,38 @@ def solve(self, step=None, method='odeint', solution_key=None, The first 3 points of the solution, in the form ``[t, x1, x2, x3]``:: - sage: sol[:3] # abs tol 1e-12 + sage: sol[:3] # abs tol 1e-12 # needs scipy [[0.0, 0.0, 0.0, 0.0], [0.05, 0.04999999218759271, -2.083327338392213e-05, 0.05], [0.1, 0.09999975001847655, -0.00016666146190783666, 0.1]] The default is ``verbose=False``:: - sage: sol_mute = c.solve(parameters_values={B_0:1, m:1, q:1, + sage: sol_mute = c.solve(parameters_values={B_0:1, m:1, q:1, # needs scipy ....: L:10, T:1}) - sage: sol_mute == sol + sage: sol_mute == sol # needs scipy True Specifying the relative and absolute error tolerance parameters to be used in :func:`~sage.calculus.desolvers.desolve_odeint`:: - sage: sol = c.solve(parameters_values={B_0:1, m:1, q:1, L:10, T:1}, + sage: sol = c.solve(parameters_values={B_0:1, m:1, q:1, L:10, T:1}, # needs scipy ....: rtol=1e-12, atol=1e-12) Using a numerical method different from the default one:: - sage: sol = c.solve(parameters_values={B_0:1, m:1, q:1, L:10, T:1}, + sage: sol = c.solve(parameters_values={B_0:1, m:1, q:1, L:10, T:1}, # needs scipy ....: method='rk8pd') TESTS:: - sage: sol = c.solve(parameters_values={m:1, q:1, L:10, T:1}) + sage: sol = c.solve(parameters_values={m:1, q:1, L:10, T:1}) # needs scipy Traceback (most recent call last): ... ValueError: numerical values should be provided for each of the parameters [B_0, L, T, m, q] - sage: sol = c.solve(method='my method', + sage: sol = c.solve(method='my method', # needs scipy ....: parameters_values={B_0:1, m:1, q:1, L:10, T:1}) Traceback (most recent call last): ... @@ -1489,9 +1496,9 @@ def solve_across_charts(self, charts=None, step=None, solution_key=None, mapping:: sage: phi = M.diff_map(M, {(C,C): [x, y], (P,C): [r*cos(th), r*sin(th)]}) - sage: fig = P.plot(number_values=9, chart=C, mapping=phi, + sage: fig = P.plot(number_values=9, chart=C, mapping=phi, # needs sage.plot ....: color='grey', ranges= {r:(2, 6), th:(0,2*pi)}) - sage: fig += C.plot(number_values=13, chart=C, mapping=phi, + sage: fig += C.plot(number_values=13, chart=C, mapping=phi, # needs sage.plot ....: color='grey', ranges= {x:(-3, 3), y:(-3, 3)}) There is a clear non-empty intersection between the two @@ -1559,9 +1566,9 @@ def solve_across_charts(self, charts=None, step=None, solution_key=None, :meth:`plot_integrated` again on each part. Finally, ``color`` can be a list, which will be cycled through:: - sage: fig += c.plot_integrated(mapping=phi, color=["green","red"], + sage: fig += c.plot_integrated(mapping=phi, color=["green","red"], # needs sage.plot ....: thickness=3, plot_points=100, across_charts=True) - sage: fig + sage: fig # needs sage.plot Graphics object consisting of 43 graphics primitives .. PLOT:: @@ -1856,6 +1863,8 @@ def solution(self, solution_key=None, verbose=False): sage: Tp = M.tangent_space(p) sage: v = Tp((1,0,1)) sage: c = M.integrated_curve(eqns, D, (t,0,5), v, name='c') + + sage: # needs scipy sage: sol = c.solve(solution_key='sol_T1', ....: parameters_values={B_0:1, m:1, q:1, L:10, T:1}) sage: sol_bis = c.solution(verbose=True) @@ -1928,6 +1937,8 @@ def interpolate(self, solution_key=None, method=None, sage: Tp = M.tangent_space(p) sage: v = Tp((1,0,1)) sage: c = M.integrated_curve(eqns, D, (t,0,5), v, name='c') + + sage: # needs scipy sage: sol = c.solve(method='odeint', ....: solution_key='sol_T1', ....: parameters_values={B_0:1, m:1, q:1, L:10, T:1}) @@ -2057,6 +2068,8 @@ def interpolation(self, interpolation_key=None, verbose=False): sage: Tp = M.tangent_space(p) sage: v = Tp((1,0,1)) sage: c = M.integrated_curve(eqns, D, (t,0,5), v, name='c') + + sage: # needs scipy sage: sol = c.solve(method='odeint', ....: solution_key='sol_T1', ....: parameters_values={B_0:1, m:1, q:1, L:10, T:1}) @@ -2131,6 +2144,8 @@ def __call__(self, t, interpolation_key=None, sage: Tp = M.tangent_space(p) sage: v = Tp((1,0,1)) sage: c = M.integrated_curve(eqns, D, (t,0,5), v, name='c') + + sage: # needs scipy sage: sol = c.solve(method='odeint', ....: solution_key='sol_T1', ....: parameters_values={B_0:1, m:1, q:1, L:10, T:1}) @@ -2213,6 +2228,8 @@ def tangent_vector_eval_at(self, t, sage: Tp = M.tangent_space(p) sage: v = Tp((1,0,1)) sage: c = M.integrated_curve(eqns, D, (t,0,5), v, name='c') + + sage: # needs scipy sage: sol = c.solve(method='odeint', ....: solution_key='sol_T1', ....: parameters_values={B_0:1, m:1, q:1, L:10, T:1}) @@ -2327,6 +2344,8 @@ def plot_integrated(self, chart=None, ambient_coords=None, sage: Tp = M.tangent_space(p) sage: v = Tp((1,0,1)) sage: c = M.integrated_curve(eqns, D, (t,0,6), v, name='c') + + sage: # needs scipy sage: sol = c.solve() sage: interp = c.interpolate() sage: c_plot_2d = c.plot_integrated(ambient_coords=[x1, x2], @@ -3756,6 +3775,7 @@ class IntegratedGeodesic(IntegratedAutoparallelCurve): Solve, interpolate and prepare the plot for the solutions corresponding to the three initial conditions previously set:: + sage: # needs scipy sage.plot sage: graph3D_embedded_geods = Graphics() sage: for key in dict_params: ....: sol = c.solve(solution_key='sol-'+key, @@ -3770,6 +3790,7 @@ class IntegratedGeodesic(IntegratedAutoparallelCurve): Plot the resulting geodesics on the grid of polar coordinates lines on `\mathbb{S}^{2}` and check that these are great circles:: + sage: # needs scipy sage.plot sage: graph3D_embedded_polar_coords = polar.plot(chart=cart, ....: mapping=euclid_embedding, ....: number_values=15, color='yellow') diff --git a/src/sage/manifolds/differentiable/multivectorfield.py b/src/sage/manifolds/differentiable/multivectorfield.py index 2590803b0fa..87f68f8b1f0 100644 --- a/src/sage/manifolds/differentiable/multivectorfield.py +++ b/src/sage/manifolds/differentiable/multivectorfield.py @@ -1404,18 +1404,20 @@ def bracket(self, other): Finally let us check the graded Jacobi identity for `p=1`, `q=1` and `r=2`:: - sage: a_bc = a.bracket(b.bracket(c)) # long time - sage: b_ca = b.bracket(c.bracket(a)) # long time - sage: c_ab = c.bracket(a.bracket(b)) # long time - sage: a_bc + b_ca + c_ab == 0 # long time + sage: # long time + sage: a_bc = a.bracket(b.bracket(c)) + sage: b_ca = b.bracket(c.bracket(a)) + sage: c_ab = c.bracket(a.bracket(b)) + sage: a_bc + b_ca + c_ab == 0 True as well as for `p=1`, `q=2` and `r=2`:: - sage: a_cd = a.bracket(c.bracket(d)) # long time - sage: c_da = c.bracket(d.bracket(a)) # long time - sage: d_ac = d.bracket(a.bracket(c)) # long time - sage: a_cd + c_da - d_ac == 0 # long time + sage: # long time + sage: a_cd = a.bracket(c.bracket(d)) + sage: c_da = c.bracket(d.bracket(a)) + sage: d_ac = d.bracket(a.bracket(c)) + sage: a_cd + c_da - d_ac == 0 True """ diff --git a/src/sage/manifolds/differentiable/pseudo_riemannian_submanifold.py b/src/sage/manifolds/differentiable/pseudo_riemannian_submanifold.py index 3aef31eb703..b41b8ba4ba8 100644 --- a/src/sage/manifolds/differentiable/pseudo_riemannian_submanifold.py +++ b/src/sage/manifolds/differentiable/pseudo_riemannian_submanifold.py @@ -115,13 +115,14 @@ Let us compute the induced metric (or first fundamental form):: - sage: gamma = N.induced_metric() # long time - sage: gamma.display() # long time + sage: # long time + sage: gamma = N.induced_metric() + sage: gamma.display() gamma = b^2 drh⊗drh + b^2*sinh(rh)^2 dth⊗dth - sage: gamma[:] # long time + sage: gamma[:] [ b^2 0] [ 0 b^2*sinh(rh)^2] - sage: gamma[1,1] # long time + sage: gamma[1,1] b^2 the normal vector:: diff --git a/src/sage/manifolds/differentiable/tangent_vector.py b/src/sage/manifolds/differentiable/tangent_vector.py index 5fc2506b1d0..97abcea54e1 100644 --- a/src/sage/manifolds/differentiable/tangent_vector.py +++ b/src/sage/manifolds/differentiable/tangent_vector.py @@ -261,12 +261,12 @@ def plot(self, chart=None, ambient_coords=None, mapping=None, Plot of the vector alone (arrow + label):: - sage: v.plot() + sage: v.plot() # needs sage.plot Graphics object consisting of 2 graphics primitives Plot atop of the chart grid:: - sage: X.plot() + v.plot() + sage: X.plot() + v.plot() # needs sage.plot Graphics object consisting of 20 graphics primitives .. PLOT:: @@ -280,7 +280,7 @@ def plot(self, chart=None, ambient_coords=None, mapping=None, Plots with various options:: - sage: X.plot() + v.plot(color='green', scale=2, label='V') + sage: X.plot() + v.plot(color='green', scale=2, label='V') # needs sage.plot Graphics object consisting of 20 graphics primitives .. PLOT:: @@ -294,7 +294,7 @@ def plot(self, chart=None, ambient_coords=None, mapping=None, :: - sage: X.plot() + v.plot(print_label=False) + sage: X.plot() + v.plot(print_label=False) # needs sage.plot Graphics object consisting of 19 graphics primitives .. PLOT:: @@ -308,7 +308,7 @@ def plot(self, chart=None, ambient_coords=None, mapping=None, :: - sage: X.plot() + v.plot(color='green', label_color='black', + sage: X.plot() + v.plot(color='green', label_color='black', # needs sage.plot ....: fontsize=20, label_offset=0.2) Graphics object consisting of 20 graphics primitives @@ -323,7 +323,7 @@ def plot(self, chart=None, ambient_coords=None, mapping=None, :: - sage: X.plot() + v.plot(linestyle=':', width=4, arrowsize=8, + sage: X.plot() + v.plot(linestyle=':', width=4, arrowsize=8, # needs sage.plot ....: fontsize=20) Graphics object consisting of 20 graphics primitives @@ -342,7 +342,7 @@ def plot(self, chart=None, ambient_coords=None, mapping=None, (a, b) sage: v = Tp((1+a, -b^2), name='v') ; v.display() v = (a + 1) ∂/∂x - b^2 ∂/∂y - sage: X.plot() + v.plot(parameters={a: -2, b: 3}) + sage: X.plot() + v.plot(parameters={a: -2, b: 3}) # needs sage.plot Graphics object consisting of 20 graphics primitives Special case of the zero vector:: @@ -350,7 +350,7 @@ def plot(self, chart=None, ambient_coords=None, mapping=None, sage: v = Tp.zero() ; v Tangent vector zero at Point p on the 2-dimensional differentiable manifold M - sage: X.plot() + v.plot() + sage: X.plot() + v.plot() # needs sage.plot Graphics object consisting of 19 graphics primitives Vector tangent to a 4-dimensional manifold:: @@ -365,7 +365,7 @@ def plot(self, chart=None, ambient_coords=None, mapping=None, We cannot make a 4D plot directly:: - sage: v.plot() + sage: v.plot() # needs sage.plot Traceback (most recent call last): ... ValueError: the number of coordinates involved in the plot must @@ -375,7 +375,7 @@ def plot(self, chart=None, ambient_coords=None, mapping=None, the argument ``ambient_coords``. For instance, for a 2-dimensional plot in terms of the coordinates `(x, y)`:: - sage: v.plot(ambient_coords=(x,y)) + sage: v.plot(ambient_coords=(x,y)) # needs sage.plot Graphics object consisting of 2 graphics primitives .. PLOT:: @@ -391,14 +391,14 @@ def plot(self, chart=None, ambient_coords=None, mapping=None, Similarly, for a 3-dimensional plot in terms of the coordinates `(t, x, y)`:: - sage: g = v.plot(ambient_coords=(t,x,z)) - sage: print(g) + sage: g = v.plot(ambient_coords=(t,x,z)) # needs sage.plot + sage: print(g) # needs sage.plot Graphics3d Object This plot involves only the components `v^t`, `v^x` and `v^z` of `v`. A nice 3D view atop the coordinate grid is obtained via:: - sage: (X.plot(ambient_coords=(t,x,z)) # long time + sage: (X.plot(ambient_coords=(t,x,z)) # long time # needs sage.plot ....: + v.plot(ambient_coords=(t,x,z), ....: label_offset=0.5, width=6)) Graphics3d Object @@ -431,9 +431,9 @@ def plot(self, chart=None, ambient_coords=None, mapping=None, sage: v = XS.frame()[1].at(p) ; v # the coordinate vector ∂/∂phi at p Tangent vector ∂/∂ph at Point p on the 2-dimensional differentiable manifold S^2 - sage: graph_v = v.plot(mapping=F) - sage: graph_S2 = XS.plot(chart=X3, mapping=F, number_values=9) # long time - sage: graph_v + graph_S2 # long time + sage: graph_v = v.plot(mapping=F) # needs sage.plot + sage: graph_S2 = XS.plot(chart=X3, mapping=F, number_values=9) # long time, needs sage.plot + sage: graph_v + graph_S2 # long time, needs sage.plot Graphics3d Object .. PLOT:: diff --git a/src/sage/manifolds/differentiable/tensorfield.py b/src/sage/manifolds/differentiable/tensorfield.py index 9e302688024..a47bd364436 100644 --- a/src/sage/manifolds/differentiable/tensorfield.py +++ b/src/sage/manifolds/differentiable/tensorfield.py @@ -245,17 +245,18 @@ class TensorField(ModuleElementWithMutability): The vectors can be defined only on subsets of `S^2`, the domain of the result is then the common subset:: - sage: s = t(a.restrict(U), b) ; s # long time + sage: # long time + sage: s = t(a.restrict(U), b) ; s Scalar field t(a,b) on the Open subset U of the 2-dimensional differentiable manifold S^2 - sage: s.display() # long time + sage: s.display() t(a,b): U → ℝ (x, y) ↦ -2*x*y - y^2 - 3*x on W: (u, v) ↦ -(3*u^3 + (3*u + 1)*v^2 + 2*u*v)/(u^4 + 2*u^2*v^2 + v^4) - sage: s = t(a.restrict(U), b.restrict(W)) ; s # long time + sage: s = t(a.restrict(U), b.restrict(W)) ; s Scalar field t(a,b) on the Open subset W of the 2-dimensional differentiable manifold S^2 - sage: s.display() # long time + sage: s.display() t(a,b): W → ℝ (x, y) ↦ -2*x*y - y^2 - 3*x (u, v) ↦ -(3*u^3 + (3*u + 1)*v^2 + 2*u*v)/(u^4 + 2*u^2*v^2 + v^4) diff --git a/src/sage/manifolds/differentiable/vectorfield.py b/src/sage/manifolds/differentiable/vectorfield.py index 22b5df5717f..04018ba9916 100644 --- a/src/sage/manifolds/differentiable/vectorfield.py +++ b/src/sage/manifolds/differentiable/vectorfield.py @@ -465,7 +465,7 @@ def plot(self, chart=None, ambient_coords=None, mapping=None, sage: v = M.vector_field(-y, x, name='v') sage: v.display() v = -y ∂/∂x + x ∂/∂y - sage: v.plot() + sage: v.plot() # needs sage.plot Graphics object consisting of 80 graphics primitives .. PLOT:: @@ -478,7 +478,7 @@ def plot(self, chart=None, ambient_coords=None, mapping=None, Plot with various options:: - sage: v.plot(scale=0.5, color='green', linestyle='--', width=1, + sage: v.plot(scale=0.5, color='green', linestyle='--', width=1, # needs sage.plot ....: arrowsize=6) Graphics object consisting of 80 graphics primitives @@ -492,7 +492,7 @@ def plot(self, chart=None, ambient_coords=None, mapping=None, :: - sage: v.plot(max_range=4, number_values=5, scale=0.5) + sage: v.plot(max_range=4, number_values=5, scale=0.5) # needs sage.plot Graphics object consisting of 24 graphics primitives .. PLOT:: @@ -506,7 +506,7 @@ def plot(self, chart=None, ambient_coords=None, mapping=None, Plot using parallel computation:: sage: Parallelism().set(nproc=2) - sage: v.plot(scale=0.5, number_values=10, linestyle='--', width=1, + sage: v.plot(scale=0.5, number_values=10, linestyle='--', width=1, # needs sage.plot ....: arrowsize=6) Graphics object consisting of 100 graphics primitives @@ -524,7 +524,7 @@ def plot(self, chart=None, ambient_coords=None, mapping=None, Plots along a line of fixed coordinate:: - sage: v.plot(fixed_coords={x: -2}) + sage: v.plot(fixed_coords={x: -2}) # needs sage.plot Graphics object consisting of 9 graphics primitives .. PLOT:: @@ -537,7 +537,7 @@ def plot(self, chart=None, ambient_coords=None, mapping=None, :: - sage: v.plot(fixed_coords={y: 1}) + sage: v.plot(fixed_coords={y: 1}) # needs sage.plot Graphics object consisting of 9 graphics primitives .. PLOT:: @@ -566,7 +566,7 @@ def plot(self, chart=None, ambient_coords=None, mapping=None, Rather, we have to select some coordinates for the plot, via the argument ``ambient_coords``. For instance, for a 3D plot:: - sage: v.plot(ambient_coords=(x, y, z), fixed_coords={t: 1}, # long time + sage: v.plot(ambient_coords=(x, y, z), fixed_coords={t: 1}, # long time, needs sage.plot ....: number_values=4) Graphics3d Object @@ -580,7 +580,7 @@ def plot(self, chart=None, ambient_coords=None, mapping=None, :: - sage: v.plot(ambient_coords=(x, y, t), fixed_coords={z: 0}, # long time + sage: v.plot(ambient_coords=(x, y, t), fixed_coords={z: 0}, # long time, needs sage.plot ....: ranges={x: (-2,2), y: (-2,2), t: (-1, 4)}, ....: number_values=4) Graphics3d Object @@ -596,7 +596,7 @@ def plot(self, chart=None, ambient_coords=None, mapping=None, or, for a 2D plot:: - sage: v.plot(ambient_coords=(x, y), fixed_coords={t: 1, z: 0}) # long time + sage: v.plot(ambient_coords=(x, y), fixed_coords={t: 1, z: 0}) # long time, needs sage.plot Graphics object consisting of 80 graphics primitives .. PLOT:: @@ -609,7 +609,7 @@ def plot(self, chart=None, ambient_coords=None, mapping=None, :: - sage: v.plot(ambient_coords=(x, t), fixed_coords={y: 1, z: 0}) # long time + sage: v.plot(ambient_coords=(x, t), fixed_coords={y: 1, z: 0}) # long time, needs sage.plot Graphics object consisting of 72 graphics primitives .. PLOT:: @@ -636,9 +636,9 @@ def plot(self, chart=None, ambient_coords=None, mapping=None, sage: v = XS.frame()[1] ; v # the coordinate vector ∂/∂phi Vector field ∂/∂ph on the Open subset U of the 2-dimensional differentiable manifold S^2 - sage: graph_v = v.plot(chart=X3, mapping=F, label_axes=False) - sage: graph_S2 = XS.plot(chart=X3, mapping=F, number_values=9) - sage: graph_v + graph_S2 + sage: graph_v = v.plot(chart=X3, mapping=F, label_axes=False) # needs sage.plot + sage: graph_S2 = XS.plot(chart=X3, mapping=F, number_values=9) # needs sage.plot + sage: graph_v + graph_S2 # needs sage.plot Graphics3d Object .. PLOT:: diff --git a/src/sage/manifolds/manifold.py b/src/sage/manifolds/manifold.py index b19177da9e5..0e09530ad54 100644 --- a/src/sage/manifolds/manifold.py +++ b/src/sage/manifolds/manifold.py @@ -455,7 +455,7 @@ class being :class:`~sage.manifolds.point.ManifoldPoint`. A manifold over `\QQ_5`, the field of 5-adic numbers:: - sage: N = Manifold(2, 'N', structure='topological', field=Qp(5)); N + sage: N = Manifold(2, 'N', structure='topological', field=Qp(5)); N # needs sage.rings.padics 2-dimensional topological manifold N over the 5-adic Field with capped relative precision 20 @@ -474,7 +474,7 @@ class being :class:`~sage.manifolds.point.ManifoldPoint`. True sage: M in Manifolds(RR) True - sage: N in Manifolds(Qp(5)) + sage: N in Manifolds(Qp(5)) # needs sage.rings.padics True The corresponding Sage *elements* are points:: diff --git a/src/sage/manifolds/point.py b/src/sage/manifolds/point.py index 728269ed5ea..ff0009db15b 100644 --- a/src/sage/manifolds/point.py +++ b/src/sage/manifolds/point.py @@ -803,6 +803,7 @@ def plot(self, chart=None, ambient_coords=None, mapping=None, Drawing a point on a 2-dimensional manifold:: + sage: # needs sage.plot sage: M = Manifold(2, 'M', structure='topological') sage: X. = M.chart() sage: p = M.point((1,3), name='p') @@ -826,12 +827,14 @@ def plot(self, chart=None, ambient_coords=None, mapping=None, ``p`` has been defined, it can be skipped in the arguments of ``plot``:: + sage: # needs sage.plot sage: g = p.plot() sage: g + gX Graphics object consisting of 20 graphics primitives Call with some options:: + sage: # needs sage.plot sage: g = p.plot(chart=X, size=40, color='green', label='$P$', ....: label_color='blue', fontsize=20, label_offset=0.3) sage: g + gX @@ -851,9 +854,9 @@ def plot(self, chart=None, ambient_coords=None, mapping=None, symbolic variable:: sage: a = var('a') - sage: q = M.point((a,2*a), name='q') - sage: gq = q.plot(parameters={a:-2}, label_offset=0.2) - sage: g + gX + gq + sage: q = M.point((a,2*a), name='q') # needs sage.plot + sage: gq = q.plot(parameters={a:-2}, label_offset=0.2) # needs sage.plot + sage: g + gX + gq # needs sage.plot Graphics object consisting of 22 graphics primitives .. PLOT:: @@ -871,11 +874,12 @@ def plot(self, chart=None, ambient_coords=None, mapping=None, The numerical value is used only for the plot:: - sage: q.coord() + sage: q.coord() # needs sage.plot (a, 2*a) Drawing a point on a 3-dimensional manifold:: + sage: # needs sage.plot sage: M = Manifold(3, 'M', structure='topological') sage: X. = M.chart() sage: p = M.point((2,1,3), name='p') @@ -888,16 +892,17 @@ def plot(self, chart=None, ambient_coords=None, mapping=None, Call with some options:: - sage: g = p.plot(chart=X, size=40, color='green', label='P_1', + sage: g = p.plot(chart=X, size=40, color='green', label='P_1', # needs sage.plot ....: label_color='blue', fontsize=20, label_offset=0.3) - sage: g + gX + sage: g + gX # needs sage.plot Graphics3d Object An example of plot via a mapping: plot of a point on a 2-sphere viewed in the 3-dimensional space ``M``:: + sage: # needs sage.plot sage: S2 = Manifold(2, 'S^2', structure='topological') - sage: U = S2.open_subset('U') # the open set covered by spherical coord. + sage: U = S2.open_subset('U') # the open set covered by spherical coord. sage: XS. = U.chart(r'th:(0,pi):\theta ph:(0,2*pi):\phi') sage: p = U.point((pi/4, pi/8), name='p') sage: F = S2.continuous_map(M, {(XS, X): [sin(th)*cos(ph), @@ -913,6 +918,7 @@ def plot(self, chart=None, ambient_coords=None, mapping=None, Use of the option ``ambient_coords`` for plots on a 4-dimensional manifold:: + sage: # needs sage.plot sage: M = Manifold(4, 'M', structure='topological') sage: X. = M.chart() sage: p = M.point((1,2,3,4), name='p') diff --git a/src/sage/manifolds/subset.py b/src/sage/manifolds/subset.py index b92d8a25d82..cd98b143037 100644 --- a/src/sage/manifolds/subset.py +++ b/src/sage/manifolds/subset.py @@ -897,11 +897,12 @@ def subset_digraph(self, loops=False, quotient=False, open_covers=False, points= EXAMPLES:: + sage: # needs sage.graphs sage: M = Manifold(3, 'M') sage: U = M.open_subset('U'); V = M.open_subset('V'); W = M.open_subset('W') sage: D = M.subset_digraph(); D Digraph on 4 vertices - sage: D.edges(sort=True, key=lambda e: (e[0]._name, e[1]._name)) + sage: D.edges(sort=True, key=lambda e: (e[0]._name, e[1]._name)) # needs sage.graphs [(Set {U} of open subsets of the 3-dimensional differentiable manifold M, Set {M} of open subsets of the 3-dimensional differentiable manifold M, None), @@ -911,27 +912,26 @@ def subset_digraph(self, loops=False, quotient=False, open_covers=False, points= (Set {W} of open subsets of the 3-dimensional differentiable manifold M, Set {M} of open subsets of the 3-dimensional differentiable manifold M, None)] - sage: D.plot(layout='acyclic') + sage: D.plot(layout='acyclic') # needs sage.plot Graphics object consisting of 8 graphics primitives sage: def label(element): ....: try: ....: return element._name ....: except AttributeError: ....: return '[' + ', '.join(sorted(x._name for x in element)) + ']' - sage: D.relabel(label, inplace=False).plot(layout='acyclic') + sage: D.relabel(label, inplace=False).plot(layout='acyclic') # needs sage.plot Graphics object consisting of 8 graphics primitives - sage: VW = V.union(W) sage: D = M.subset_digraph(); D Digraph on 5 vertices - sage: D.relabel(label, inplace=False).plot(layout='acyclic') + sage: D.relabel(label, inplace=False).plot(layout='acyclic') # needs sage.plot Graphics object consisting of 12 graphics primitives If ``open_covers`` is ``True``, the digraph includes a special vertex for each nontrivial open cover of a subset:: - sage: D = M.subset_digraph(open_covers=True) - sage: D.relabel(label, inplace=False).plot(layout='acyclic') + sage: D = M.subset_digraph(open_covers=True) # needs sage.graphs + sage: D.relabel(label, inplace=False).plot(layout='acyclic') # needs sage.graphs sage.plot Graphics object consisting of 14 graphics primitives .. PLOT:: @@ -1057,11 +1057,12 @@ def subset_poset(self, open_covers=False, points=False, lower_bound=None): EXAMPLES:: + sage: # needs sage.graphs sage: M = Manifold(3, 'M') sage: U = M.open_subset('U'); V = M.open_subset('V'); W = M.open_subset('W') sage: P = M.subset_poset(); P Finite poset containing 4 elements - sage: P.plot(element_labels={element: element._name for element in P}) + sage: P.plot(element_labels={element: element._name for element in P}) # needs sage.plot Graphics object consisting of 8 graphics primitives sage: VW = V.union(W) sage: P = M.subset_poset(); P @@ -1076,12 +1077,13 @@ def subset_poset(self, open_covers=False, points=False, lower_bound=None): sage: sorted(P.lower_covers(ManifoldSubsetFiniteFamily([M])), key=str) [Set {U} of open subsets of the 3-dimensional differentiable manifold M, Set {V_union_W} of open subsets of the 3-dimensional differentiable manifold M] - sage: P.plot(element_labels={element: element._name for element in P}) + sage: P.plot(element_labels={element: element._name for element in P}) # needs sage.plot Graphics object consisting of 10 graphics primitives If ``open_covers`` is ``True``, the poset includes a special vertex for each nontrivial open cover of a subset:: + sage: # needs sage.graphs sage: P = M.subset_poset(open_covers=True); P Finite poset containing 6 elements sage: from sage.manifolds.subset import ManifoldSubsetFiniteFamily @@ -1094,7 +1096,7 @@ def subset_poset(self, open_covers=False, points=False, lower_bound=None): ....: return element._name ....: except AttributeError: ....: return '[' + ', '.join(sorted(x._name for x in element)) + ']' - sage: P.plot(element_labels={element: label(element) for element in P}) + sage: P.plot(element_labels={element: label(element) for element in P}) # needs sage.plot Graphics object consisting of 12 graphics primitives .. PLOT:: @@ -1236,7 +1238,7 @@ def superset_digraph(self, loops=False, quotient=False, open_covers=False, point sage: M = Manifold(3, 'M') sage: U = M.open_subset('U'); V = M.open_subset('V'); W = M.open_subset('W') sage: VW = V.union(W) - sage: P = V.superset_digraph(loops=False, upper_bound=VW); P + sage: P = V.superset_digraph(loops=False, upper_bound=VW); P # needs sage.graphs Digraph on 2 vertices """ @@ -1261,9 +1263,9 @@ def superset_poset(self, open_covers=False, points=False, upper_bound=None): sage: M = Manifold(3, 'M') sage: U = M.open_subset('U'); V = M.open_subset('V'); W = M.open_subset('W') sage: VW = V.union(W) - sage: P = V.superset_poset(); P + sage: P = V.superset_poset(); P # needs sage.graphs Finite poset containing 3 elements - sage: P.plot(element_labels={element: element._name for element in P}) + sage: P.plot(element_labels={element: element._name for element in P}) # needs sage.graphs sage.plot Graphics object consisting of 6 graphics primitives """ @@ -1369,25 +1371,25 @@ def declare_union(self, *subsets_or_families, disjoint=False): ....: return element._name ....: except AttributeError: ....: return '[' + ', '.join(sorted(x._name for x in element)) + ']' - sage: P = M.subset_poset(open_covers=True); P + sage: P = M.subset_poset(open_covers=True); P # needs sage.graphs Finite poset containing 4 elements - sage: P.plot(element_labels={element: label(element) for element in P}) + sage: P.plot(element_labels={element: label(element) for element in P}) # needs sage.graphs sage.plot Graphics object consisting of 8 graphics primitives sage: AB.declare_union(A, B) sage: A.union(B) Subset AB of the 2-dimensional topological manifold M - sage: P = M.subset_poset(open_covers=True); P + sage: P = M.subset_poset(open_covers=True); P # needs sage.graphs Finite poset containing 4 elements - sage: P.plot(element_labels={element: label(element) for element in P}) + sage: P.plot(element_labels={element: label(element) for element in P}) # needs sage.graphs sage.plot Graphics object consisting of 8 graphics primitives sage: B1 = B.subset('B1', is_open=True) sage: B2 = B.subset('B2', is_open=True) sage: B.declare_union(B1, B2, disjoint=True) - sage: P = M.subset_poset(open_covers=True); P + sage: P = M.subset_poset(open_covers=True); P # needs sage.graphs Finite poset containing 9 elements - sage: P.plot(element_labels={element: label(element) for element in P}) + sage: P.plot(element_labels={element: label(element) for element in P}) # needs sage.graphs sage.plot Graphics object consisting of 19 graphics primitives .. PLOT:: @@ -1495,18 +1497,18 @@ def declare_equal(self, *others): sage: Vs = [M.open_subset(f'V{i}') for i in range(2)] sage: UV = U.intersection(V) sage: W = UV.open_subset('W') - sage: P = M.subset_poset() + sage: P = M.subset_poset() # needs sage.graphs sage: def label(element): ....: return element._name - sage: P.plot(element_labels={element: label(element) for element in P}) + sage: P.plot(element_labels={element: label(element) for element in P}) # needs sage.graphs sage.plot Graphics object consisting of 15 graphics primitives sage: V.declare_equal(Vs) - sage: P = M.subset_poset() - sage: P.plot(element_labels={element: label(element) for element in P}) + sage: P = M.subset_poset() # needs sage.graphs + sage: P.plot(element_labels={element: label(element) for element in P}) # needs sage.graphs sage.plot Graphics object consisting of 11 graphics primitives sage: W.declare_equal(U) - sage: P = M.subset_poset() - sage: P.plot(element_labels={element: label(element) for element in P}) + sage: P = M.subset_poset() # needs sage.graphs + sage: P.plot(element_labels={element: label(element) for element in P}) # needs sage.graphs sage.plot Graphics object consisting of 6 graphics primitives .. PLOT:: @@ -1557,16 +1559,16 @@ def declare_subset(self, *supersets): Set {M, V} of open subsets of the 2-dimensional differentiable manifold M sage: U1.subset_family() Set {U1} of open subsets of the 2-dimensional differentiable manifold M - sage: P = M.subset_poset() + sage: P = M.subset_poset() # needs sage.graphs sage: def label(element): ....: return element._name - sage: P.plot(element_labels={element: label(element) for element in P}) + sage: P.plot(element_labels={element: label(element) for element in P}) # needs sage.graphs sage.plot Graphics object consisting of 8 graphics primitives sage: V.declare_subset(U1, U2) sage: V.superset_family() Set {M, U1, U2, V} of open subsets of the 2-dimensional differentiable manifold M - sage: P = M.subset_poset() - sage: P.plot(element_labels={element: label(element) for element in P}) + sage: P = M.subset_poset() # needs sage.graphs + sage: P.plot(element_labels={element: label(element) for element in P}) # needs sage.graphs sage.plot Graphics object consisting of 9 graphics primitives Subsets in a directed cycle of inclusions are equal:: @@ -1576,8 +1578,8 @@ def declare_subset(self, *supersets): Set {M, U1, U2, V} of open subsets of the 2-dimensional differentiable manifold M sage: M.equal_subset_family() Set {M, U1, U2, V} of open subsets of the 2-dimensional differentiable manifold M - sage: P = M.subset_poset() - sage: P.plot(element_labels={element: label(element) for element in P}) + sage: P = M.subset_poset() # needs sage.graphs + sage: P.plot(element_labels={element: label(element) for element in P}) # needs sage.graphs sage.plot Graphics object consisting of 2 graphics primitives .. PLOT:: @@ -1623,16 +1625,16 @@ def declare_superset(self, *subsets): sage: W = V1.intersection(V2) sage: U.subset_family() Set {U} of open subsets of the 2-dimensional differentiable manifold M - sage: P = M.subset_poset() + sage: P = M.subset_poset() # needs sage.graphs sage: def label(element): ....: return element._name - sage: P.plot(element_labels={element: label(element) for element in P}) + sage: P.plot(element_labels={element: label(element) for element in P}) # needs sage.graphs sage.plot Graphics object consisting of 11 graphics primitives sage: U.declare_superset(V1, V2) sage: U.subset_family() Set {U, V1, V1_inter_V2, V2} of open subsets of the 2-dimensional differentiable manifold M - sage: P = M.subset_poset() - sage: P.plot(element_labels={element: label(element) for element in P}) + sage: P = M.subset_poset() # needs sage.graphs + sage: P.plot(element_labels={element: label(element) for element in P}) # needs sage.graphs sage.plot Graphics object consisting of 11 graphics primitives Subsets in a directed cycle of inclusions are equal:: @@ -1642,8 +1644,8 @@ def declare_superset(self, *subsets): Set {U, V1, V1_inter_V2, V2} of open subsets of the 2-dimensional differentiable manifold M sage: W.equal_subset_family() Set {U, V1, V1_inter_V2, V2} of open subsets of the 2-dimensional differentiable manifold M - sage: P = M.subset_poset() - sage: P.plot(element_labels={element: label(element) for element in P}) + sage: P = M.subset_poset() # needs sage.graphs + sage: P.plot(element_labels={element: label(element) for element in P}) # needs sage.graphs sage.plot Graphics object consisting of 4 graphics primitives .. PLOT:: @@ -1726,7 +1728,7 @@ def declare_empty(self): Emptiness is recorded as empty open covers:: - sage: P = M.subset_poset(open_covers=True, points=[b]) + sage: P = M.subset_poset(open_covers=True, points=[b]) # needs sage.graphs sage: def label(element): ....: if isinstance(element, str): ....: return element @@ -1734,7 +1736,7 @@ def declare_empty(self): ....: return element._name ....: except AttributeError: ....: return '[' + ', '.join(sorted(x._name for x in element)) + ']' - sage: P.plot(element_labels={element: label(element) for element in P}) + sage: P.plot(element_labels={element: label(element) for element in P}) # needs sage.graphs sage.plot Graphics object consisting of 10 graphics primitives .. PLOT:: diff --git a/src/sage/manifolds/subsets/pullback.py b/src/sage/manifolds/subsets/pullback.py index b28365601f8..452b6a2e008 100644 --- a/src/sage/manifolds/subsets/pullback.py +++ b/src/sage/manifolds/subsets/pullback.py @@ -15,6 +15,7 @@ from sage.categories.sets_cat import Sets, EmptySetError from sage.categories.metric_spaces import MetricSpaces +from sage.misc.lazy_import import lazy_import from sage.modules.free_module import is_FreeModule from sage.rings.infinity import infinity, minus_infinity from sage.rings.integer_ring import ZZ @@ -29,7 +30,8 @@ from sage.manifolds.scalarfield import ScalarField from sage.sets.real_set import RealSet import sage.geometry.abc -from sage.geometry.relative_interior import RelativeInterior + +lazy_import('sage.geometry.relative_interior', 'RelativeInterior') class ManifoldSubsetPullback(ManifoldSubset): @@ -77,6 +79,7 @@ class ManifoldSubsetPullback(ManifoldSubset): Pulling back a polytope under a chart:: + sage: # needs sage.geometry.polyhedron sage: P = Polyhedron(vertices=[[0, 0], [1, 2], [2, 1]]); P A 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 3 vertices sage: S = ManifoldSubsetPullback(c_cart, P); S @@ -88,8 +91,10 @@ class ManifoldSubsetPullback(ManifoldSubset): Pulling back the interior of a polytope under a chart:: + sage: # needs sage.geometry.polyhedron sage: int_P = P.interior(); int_P - Relative interior of a 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 3 vertices + Relative interior of a + 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 3 vertices sage: int_S = ManifoldSubsetPullback(c_cart, int_P, name='int_S'); int_S Open subset int_S of the 2-dimensional topological manifold R^2 sage: M((0, 0)) in int_S @@ -100,9 +105,9 @@ class ManifoldSubsetPullback(ManifoldSubset): Using the embedding map of a submanifold:: sage: M = Manifold(3, 'M', structure="topological") - sage: N = Manifold(2, 'N', ambient=M, structure="topological") - sage: N - 2-dimensional topological submanifold N immersed in the 3-dimensional topological manifold M + sage: N = Manifold(2, 'N', ambient=M, structure="topological"); N + 2-dimensional topological submanifold N + immersed in the 3-dimensional topological manifold M sage: CM. = M.chart() sage: CN. = N.chart() sage: t = var('t') @@ -115,7 +120,9 @@ class ManifoldSubsetPullback(ManifoldSubset): sage: from sage.manifolds.subsets.pullback import ManifoldSubsetPullback sage: S = M.open_subset('S', coord_def={CM: z<1}) - sage: phi_without_t = N.continuous_map(M, {(CN, CM): [expr.subs(t=0) for expr in phi.expr()]}); phi_without_t + sage: phi_without_t = N.continuous_map(M, {(CN, CM): [expr.subs(t=0) + ....: for expr in phi.expr()]}) + sage: phi_without_t Continuous map from the 2-dimensional topological submanifold N embedded in the 3-dimensional topological manifold M @@ -123,7 +130,8 @@ class ManifoldSubsetPullback(ManifoldSubset): sage: phi_without_t.expr() (u, v, u^2 + v^2) sage: D = ManifoldSubsetPullback(phi_without_t, S); D - Subset f_inv_S of the 2-dimensional topological submanifold N embedded in the 3-dimensional topological manifold M + Subset f_inv_S of the 2-dimensional topological submanifold N + embedded in the 3-dimensional topological manifold M sage: N.point((2,0)) in D False @@ -136,6 +144,7 @@ def __classcall_private__(cls, map, codomain_subset, inverse=None, TESTS:: + sage: # needs sage.geometry.polyhedron sage: from sage.manifolds.subsets.pullback import ManifoldSubsetPullback sage: M = Manifold(2, 'R^2', structure='topological') sage: c_cart. = M.chart() # Cartesian coordinates on R^2 @@ -243,6 +252,7 @@ def _is_open(codomain_subset): Polyhedra:: + sage: # needs sage.geometry.polyhedron sage: Empty = Polyhedron(ambient_dim=2); Empty The empty polyhedron in ZZ^2 sage: ManifoldSubsetPullback._is_open(Empty) @@ -254,30 +264,32 @@ def _is_open(codomain_subset): Interiors of polyhedra:: - sage: int_C = C.interior(); int_C - Relative interior of a 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 8 vertices - sage: ManifoldSubsetPullback._is_open(int_C) + sage: int_C = C.interior(); int_C # needs sage.geometry.polyhedron + Relative interior of a + 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 8 vertices + sage: ManifoldSubsetPullback._is_open(int_C) # needs sage.geometry.polyhedron True PPL polyhedra and not-necessarily-closed polyhedra:: - sage: from ppl import Variable, C_Polyhedron, NNC_Polyhedron, Constraint_System # optional - pplpy - sage: u = Variable(0) # optional - pplpy - sage: v = Variable(1) # optional - pplpy - sage: CS = Constraint_System() # optional - pplpy - sage: CS.insert(0 < u) # optional - pplpy - sage: CS.insert(u < 1) # optional - pplpy - sage: CS.insert(0 < v) # optional - pplpy - sage: CS.insert(v < 1) # optional - pplpy - sage: CS.insert(u + v <= 3) # redundant inequality # optional - pplpy - sage: P = NNC_Polyhedron(CS); P # optional - pplpy + sage: # needs pplpy + sage: from ppl import Variable, C_Polyhedron, NNC_Polyhedron, Constraint_System + sage: u = Variable(0) + sage: v = Variable(1) + sage: CS = Constraint_System() + sage: CS.insert(0 < u) + sage: CS.insert(u < 1) + sage: CS.insert(0 < v) + sage: CS.insert(v < 1) + sage: CS.insert(u + v <= 3) # redundant inequality + sage: P = NNC_Polyhedron(CS); P A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 1 point, 4 closure_points - sage: ManifoldSubsetPullback._is_open(P) # optional - pplpy + sage: ManifoldSubsetPullback._is_open(P) True - sage: CS.insert(u + v <= 1) # optional - pplpy - sage: T = NNC_Polyhedron(CS); T # optional - pplpy + sage: CS.insert(u + v <= 1) + sage: T = NNC_Polyhedron(CS); T A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 1 point, 3 closure_points - sage: ManifoldSubsetPullback._is_open(T) # optional - pplpy + sage: ManifoldSubsetPullback._is_open(T) False """ @@ -454,10 +466,10 @@ def _polyhedron_restriction(expr, polyhedron, relint=False): sage: _polyhedron_restriction = ManifoldSubsetPullback._polyhedron_restriction sage: var('x y z') (x, y, z) - sage: c = polytopes.cube() - sage: _polyhedron_restriction((x, y, z), c) + sage: c = polytopes.cube() # needs sage.geometry.polyhedron + sage: _polyhedron_restriction((x, y, z), c) # needs sage.geometry.polyhedron [-x + 1 >= 0, -y + 1 >= 0, -z + 1 >= 0, x + 1 >= 0, z + 1 >= 0, y + 1 >= 0] - sage: _polyhedron_restriction((x, y, z), c, relint=True) + sage: _polyhedron_restriction((x, y, z), c, relint=True) # needs sage.geometry.polyhedron [-x + 1 > 0, -y + 1 > 0, -z + 1 > 0, x + 1 > 0, z + 1 > 0, y + 1 > 0] """ conjunction = [] @@ -510,16 +522,16 @@ def _coord_def(map, codomain_subset): Coordinate definition of an open chart polyhedron:: sage: c_cart. = M.chart() # Cartesian coordinates on R^2 - sage: P = Polyhedron(vertices=[[0, 0], [1, 2], [3, 4]]); P + sage: P = Polyhedron(vertices=[[0, 0], [1, 2], [3, 4]]); P # needs sage.geometry.polyhedron A 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 3 vertices - sage: ri_P = P.relative_interior(); ri_P + sage: ri_P = P.relative_interior(); ri_P # needs sage.geometry.polyhedron Relative interior of a 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 3 vertices - sage: _coord_def(c_cart, ri_P) + sage: _coord_def(c_cart, ri_P) # needs sage.geometry.polyhedron {Chart (R^2, (x, y)): [2*x - y > 0, -4*x + 3*y > 0, x - y + 1 > 0]} Coordinate definition of the pullback of an open interval under a scalar field:: - sage: r_squared = M.scalar_field(x^2+y^2) + sage: r_squared = M.scalar_field(x^2 + y^2) sage: I = RealSet((1, 4)); I (1, 4) sage: _coord_def(r_squared, I) @@ -594,6 +606,7 @@ def _an_element_(self): EXAMPLES:: + sage: # needs sage.geometry.polyhedron sage: from sage.manifolds.subsets.pullback import ManifoldSubsetPullback sage: M = Manifold(3, 'R^3', structure='topological') sage: c_cart. = M.chart() # Cartesian coordinates on R^3 @@ -606,8 +619,10 @@ def _an_element_(self): sage: p.coordinates(c_cart) (0, 0, 0) + sage: # needs sage.geometry.polyhedron sage: Empty = Polyhedron(ambient_dim=3) - sage: McEmpty = ManifoldSubsetPullback(c_cart, Empty, name='McEmpty'); McEmpty + sage: McEmpty = ManifoldSubsetPullback(c_cart, Empty, name='McEmpty') + sage: McEmpty Subset McEmpty of the 3-dimensional topological manifold R^3 sage: McEmpty.an_element() Traceback (most recent call last): @@ -625,6 +640,7 @@ def some_elements(self): EXAMPLES:: + sage: # needs sage.geometry.polyhedron sage: from sage.manifolds.subsets.pullback import ManifoldSubsetPullback sage: M = Manifold(3, 'R^3', structure='topological') sage: c_cart. = M.chart() # Cartesian coordinates on R^3 @@ -647,8 +663,10 @@ def some_elements(self): (1, -1/4, 1/2), (0, -5/8, 3/4)] + sage: # needs sage.geometry.polyhedron sage: Empty = Polyhedron(ambient_dim=3) - sage: McEmpty = ManifoldSubsetPullback(c_cart, Empty, name='McEmpty'); McEmpty + sage: McEmpty = ManifoldSubsetPullback(c_cart, Empty, name='McEmpty') + sage: McEmpty Subset McEmpty of the 3-dimensional topological manifold R^3 sage: list(McEmpty.some_elements()) [] @@ -670,6 +688,7 @@ def __contains__(self, point): EXAMPLES:: + sage: # needs sage.geometry.polyhedron sage: from sage.manifolds.subsets.pullback import ManifoldSubsetPullback sage: M = Manifold(3, 'R^3', structure='topological') sage: c_cart. = M.chart() # Cartesian coordinates on R^3 @@ -722,6 +741,7 @@ def is_open(self): sage: M = Manifold(2, 'R^2', structure='topological') sage: c_cart. = M.chart() # Cartesian coordinates on R^2 + sage: # needs sage.geometry.polyhedron sage: P = Polyhedron(vertices=[[0, 0], [1, 2], [3, 4]]); P A 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 3 vertices sage: P.is_open() @@ -756,6 +776,7 @@ def is_closed(self): The pullback of a (closed convex) polyhedron under a chart is closed:: + sage: # needs sage.geometry.polyhedron sage: P = Polyhedron(vertices=[[0, 0], [1, 2], [3, 4]]); P A 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 3 vertices sage: McP = ManifoldSubsetPullback(c_cart, P, name='McP'); McP diff --git a/src/sage/manifolds/utilities.py b/src/sage/manifolds/utilities.py index 4b7c21532aa..c15a98ebbce 100644 --- a/src/sage/manifolds/utilities.py +++ b/src/sage/manifolds/utilities.py @@ -1270,6 +1270,7 @@ def set_axes_labels(graph, xlabel, ylabel, zlabel, **kwds): EXAMPLES:: + sage: # needs sage.plot sage: g = sphere() sage: g.all [Graphics3d Object]