def __init__(self, X): """ Create a Set_object This function is called by the Set function; users shouldn't call this directly. EXAMPLES:: sage: type(Set(QQ)) <class 'sage.sets.set.Set_object_with_category'> TESTS:: sage: _a, _b = get_coercion_model().canonical_coercion(Set([0]), 0) Traceback (most recent call last): ... TypeError: no common canonical parent for objects with parents: '<class 'sage.sets.set.Set_object_enumerated_with_category'>' and 'Integer Ring' """ from sage.rings.integer import is_Integer if isinstance(X, (int, long)) or is_Integer(X): # The coercion model will try to call Set_object(0) raise ValueError('underlying object cannot be an integer') Parent.__init__(self, category=Sets()) self.__object = X
def __classcall__(cls, *args, **kwds): """ Normalize input to ensure a unique representation. EXAMPLES:: sage: A = AffineSpace(2, GF(4,'a')) sage: AffineGroup(A) is AffineGroup(2,4) True sage: AffineGroup(A) is AffineGroup(2, GF(4,'a')) True sage: A = AffineGroup(2, QQ) sage: V = QQ^2 sage: A is AffineGroup(V) True """ if len(args) == 1: V = args[0] if isinstance(V, AffineGroup): return V try: degree = V.dimension_relative() except AttributeError: degree = V.dimension() ring = V.base_ring() if len(args) == 2: degree, ring = args from sage.rings.integer import is_Integer if is_Integer(ring): from sage.rings.finite_rings.finite_field_constructor import FiniteField var = kwds.get('var', 'a') ring = FiniteField(ring, var) return super(AffineGroup, cls).__classcall__(cls, degree, ring)
def pyobject(self, ex, obj): from mathics.core import expression from mathics.core.expression import Number if obj is None: return expression.Symbol('Null') elif isinstance(obj, (list, tuple)) or is_Vector(obj): return expression.Expression('List', *(from_sage(item, self.subs) for item in obj)) elif isinstance(obj, Constant): return expression.Symbol(obj._conversions.get('mathematica', obj._name)) elif is_Integer(obj): return expression.Integer(str(obj)) elif isinstance(obj, sage.Rational): rational = expression.Rational(str(obj)) if rational.value.denom() == 1: return expression.Integer(rational.value.numer()) else: return rational elif isinstance(obj, sage.RealDoubleElement) or is_RealNumber(obj): return expression.Real(str(obj)) elif is_ComplexNumber(obj): real = Number.from_string(str(obj.real())).value imag = Number.from_string(str(obj.imag())).value return expression.Complex(real, imag) elif isinstance(obj, NumberFieldElement_quadratic): # TODO: this need not be a complex number, but we assume so! real = Number.from_string(str(obj.real())).value imag = Number.from_string(str(obj.imag())).value return expression.Complex(real, imag) else: return expression.from_python(obj)
def __init__(self, degree, base_ring, category=None): """ Base class for matrix groups over generic base rings You should not use this class directly. Instead, use one of the more specialized derived classes. INPUT: - ``degree`` -- integer. The degree (matrix size) of the matrix group. - ``base_ring`` -- ring. The base ring of the matrices. TESTS:: sage: G = GL(2, QQ) sage: from sage.groups.matrix_gps.matrix_group import MatrixGroup_generic sage: isinstance(G, MatrixGroup_generic) True """ assert is_Ring(base_ring) assert is_Integer(degree) self._deg = degree if self._deg <= 0: raise ValueError('the degree must be at least 1') if (category is None) and is_FiniteField(base_ring): from sage.categories.finite_groups import FiniteGroups category = FiniteGroups() super(MatrixGroup_generic, self).__init__(base=base_ring, category=category)
def __init__(self, X): """ Create a Set_object This function is called by the Set function; users shouldn't call this directly. EXAMPLES:: sage: type(Set(QQ)) <class 'sage.sets.set.Set_object_with_category'> TESTS:: sage: _a, _b = get_coercion_model().canonical_coercion(Set([0]), 0) Traceback (most recent call last): ... TypeError: no common canonical parent for objects with parents: '<class 'sage.sets.set.Set_object_enumerated_with_category'>' and 'Integer Ring' """ from sage.rings.integer import is_Integer if isinstance(X, (int,long)) or is_Integer(X): # The coercion model will try to call Set_object(0) raise ValueError('underlying object cannot be an integer') Parent.__init__(self, category=Sets()) self.__object = X
def _check_trac_number(trac_number): """ Check that the argument is likely to be a valid trac issue number. INPUT: - ``trac_number`` -- anything. OUTPUT: This function returns nothing. A ``ValueError`` is raised if the argument can not be a valid trac number. EXAMPLES:: sage: from sage.misc.superseded import _check_trac_number sage: _check_trac_number(1) sage: _check_trac_number(int(10)) sage: _check_trac_number(long(1000)) sage: _check_trac_number('1') Traceback (most recent call last): ... ValueError: The argument "1" is not a valid trac issue number. """ from sage.rings.integer import is_Integer err = ValueError('The argument "'+str(trac_number)+'" is not a valid trac issue number.') if not (is_Integer(trac_number) or isinstance(trac_number, (int,long))): raise err if trac_number < 0: raise err
def _check_trac_number(trac_number): """ Check that the argument is likely to be a valid trac issue number. INPUT: - ``trac_number`` -- anything. OUTPUT: This function returns nothing. A ``ValueError`` is raised if the argument can not be a valid trac number. EXAMPLES:: sage: from sage.misc.superseded import _check_trac_number sage: _check_trac_number(1) sage: _check_trac_number(int(10)) sage: _check_trac_number(long(1000)) sage: _check_trac_number('1') Traceback (most recent call last): ... ValueError: The argument "1" is not a valid trac issue number. """ from sage.rings.integer import is_Integer err = ValueError('The argument "' + str(trac_number) + '" is not a valid trac issue number.') if not (is_Integer(trac_number) or isinstance(trac_number, (int, long))): raise err if trac_number < 0: raise err
def Polyhedron(vertices=None, rays=None, lines=None, ieqs=None, eqns=None, ambient_dim=None, base_ring=None, minimize=True, verbose=False, backend=None): """ Construct a polyhedron object. You may either define it with vertex/ray/line or inequalities/equations data, but not both. Redundant data will automatically be removed (unless ``minimize=False``), and the complementary representation will be computed. INPUT: - ``vertices`` -- list of point. Each point can be specified as any iterable container of ``base_ring`` elements. If ``rays`` or ``lines`` are specified but no ``vertices``, the origin is taken to be the single vertex. - ``rays`` -- list of rays. Each ray can be specified as any iterable container of ``base_ring`` elements. - ``lines`` -- list of lines. Each line can be specified as any iterable container of ``base_ring`` elements. - ``ieqs`` -- list of inequalities. Each line can be specified as any iterable container of ``base_ring`` elements. An entry equal to ``[-1,7,3,4]`` represents the inequality `7x_1+3x_2+4x_3\geq 1`. - ``eqns`` -- list of equalities. Each line can be specified as any iterable container of ``base_ring`` elements. An entry equal to ``[-1,7,3,4]`` represents the equality `7x_1+3x_2+4x_3= 1`. - ``base_ring`` -- a sub-field of the reals implemented in Sage. The field over which the polyhedron will be defined. For ``QQ`` and algebraic extensions, exact arithmetic will be used. For ``RDF``, floating point numbers will be used. Floating point arithmetic is faster but might give the wrong result for degenerate input. - ``ambient_dim`` -- integer. The ambient space dimension. Usually can be figured out automatically from the H/Vrepresentation dimensions. - ``backend`` -- string or ``None`` (default). The backend to use. Valid choices are * ``'cdd'``: use cdd (:mod:`~sage.geometry.polyhedron.backend_cdd`) with `\QQ` or `\RDF` coefficients depending on ``base_ring``. * ``'ppl'``: use ppl (:mod:`~sage.geometry.polyhedron.backend_ppl`) with `\ZZ` or `\QQ` coefficients depending on ``base_ring``. * ``'field'``: use python implementation (:mod:`~sage.geometry.polyhedron.backend_field`) for any field Some backends support further optional arguments: - ``minimize`` -- boolean (default: ``True``). Whether to immediately remove redundant H/V-representation data. Currently not used. - ``verbose`` -- boolean (default: ``False``). Whether to print verbose output for debugging purposes. Only supported by the cdd backends. OUTPUT: The polyhedron defined by the input data. EXAMPLES: Construct some polyhedra:: sage: square_from_vertices = Polyhedron(vertices = [[1, 1], [1, -1], [-1, 1], [-1, -1]]) sage: square_from_ieqs = Polyhedron(ieqs = [[1, 0, 1], [1, 1, 0], [1, 0, -1], [1, -1, 0]]) sage: list(square_from_ieqs.vertex_generator()) [A vertex at (1, -1), A vertex at (1, 1), A vertex at (-1, 1), A vertex at (-1, -1)] sage: list(square_from_vertices.inequality_generator()) [An inequality (1, 0) x + 1 >= 0, An inequality (0, 1) x + 1 >= 0, An inequality (-1, 0) x + 1 >= 0, An inequality (0, -1) x + 1 >= 0] sage: p = Polyhedron(vertices = [[1.1, 2.2], [3.3, 4.4]], base_ring=RDF) sage: p.n_inequalities() 2 The same polyhedron given in two ways:: sage: p = Polyhedron(ieqs = [[0,1,0,0],[0,0,1,0]]) sage: p.Vrepresentation() (A line in the direction (0, 0, 1), A ray in the direction (1, 0, 0), A ray in the direction (0, 1, 0), A vertex at (0, 0, 0)) sage: q = Polyhedron(vertices=[[0,0,0]], rays=[[1,0,0],[0,1,0]], lines=[[0,0,1]]) sage: q.Hrepresentation() (An inequality (1, 0, 0) x + 0 >= 0, An inequality (0, 1, 0) x + 0 >= 0) Finally, a more complicated example. Take `\mathbb{R}_{\geq 0}^6` with coordinates `a, b, \dots, f` and * The inequality `e+b \geq c+d` * The inequality `e+c \geq b+d` * The equation `a+b+c+d+e+f = 31` :: sage: positive_coords = Polyhedron(ieqs=[ ... [0, 1, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0], ... [0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 1]]) sage: P = Polyhedron(ieqs=positive_coords.inequalities() + ( ... [0,0,1,-1,-1,1,0], [0,0,-1,1,-1,1,0]), eqns=[[-31,1,1,1,1,1,1]]) sage: P A 5-dimensional polyhedron in QQ^6 defined as the convex hull of 7 vertices sage: P.dim() 5 sage: P.Vrepresentation() (A vertex at (31, 0, 0, 0, 0, 0), A vertex at (0, 0, 0, 0, 0, 31), A vertex at (0, 0, 0, 0, 31, 0), A vertex at (0, 0, 31/2, 0, 31/2, 0), A vertex at (0, 31/2, 31/2, 0, 0, 0), A vertex at (0, 31/2, 0, 0, 31/2, 0), A vertex at (0, 0, 0, 31/2, 31/2, 0)) .. NOTE:: * Once constructed, a ``Polyhedron`` object is immutable. * Although the option ``field=RDF`` allows numerical data to be used, it might not give the right answer for degenerate input data - the results can depend upon the tolerance setting of cdd. """ # Clean up the arguments vertices = _make_listlist(vertices) rays = _make_listlist(rays) lines = _make_listlist(lines) ieqs = _make_listlist(ieqs) eqns = _make_listlist(eqns) got_Vrep = (len(vertices + rays + lines) > 0) got_Hrep = (len(ieqs + eqns) > 0) if got_Vrep and got_Hrep: raise ValueError('You cannot specify both H- and V-representation.') elif got_Vrep: deduced_ambient_dim = _common_length_of(vertices, rays, lines)[1] elif got_Hrep: deduced_ambient_dim = _common_length_of(ieqs, eqns)[1] - 1 else: if ambient_dim is None: deduced_ambient_dim = 0 else: deduced_ambient_dim = ambient_dim if base_ring is None: base_ring = ZZ # set ambient_dim if ambient_dim is not None and deduced_ambient_dim != ambient_dim: raise ValueError( 'Ambient space dimension mismatch. Try removing the "ambient_dim" parameter.' ) ambient_dim = deduced_ambient_dim # figure out base_ring from sage.misc.flatten import flatten values = flatten(vertices + rays + lines + ieqs + eqns) if base_ring is not None: try: convert = not all(x.parent() is base_ring for x in values) except AttributeError: # No x.parent() method? convert = True else: from sage.rings.integer import is_Integer from sage.rings.rational import is_Rational from sage.rings.real_double import is_RealDoubleElement if all(is_Integer(x) for x in values): if got_Vrep: base_ring = ZZ else: # integral inequalities usually do not determine a lattice polytope! base_ring = QQ convert = False elif all(is_Rational(x) for x in values): base_ring = QQ convert = False elif all(is_RealDoubleElement(x) for x in values): base_ring = RDF convert = False else: try: for v in values: ZZ(v) if got_Vrep: base_ring = ZZ else: base_ring = QQ convert = True except (TypeError, ValueError): from sage.structure.sequence import Sequence values = Sequence(values) common_ring = values.universe() if QQ.has_coerce_map_from(common_ring): base_ring = QQ convert = True elif common_ring is RR: # DWIM: replace with RDF base_ring = RDF convert = True else: base_ring = common_ring convert = True # Add the origin if necesarry if got_Vrep and len(vertices) == 0: vertices = [[0] * ambient_dim] # Specific backends can override the base_ring from sage.geometry.polyhedron.parent import Polyhedra parent = Polyhedra(base_ring, ambient_dim, backend=backend) base_ring = parent.base_ring() # finally, construct the Polyhedron Hrep = Vrep = None if got_Hrep: Hrep = [ieqs, eqns] if got_Vrep: Vrep = [vertices, rays, lines] return parent(Vrep, Hrep, convert=convert, verbose=verbose)
def __call__(self, P): r""" Returns a rational point P in the abstract Homset J(K), given: 0. A point P in J = Jac(C), returning P; 1. A point P on the curve C such that J = Jac(C), where C is an odd degree model, returning [P - oo]; 2. A pair of points (P, Q) on the curve C such that J = Jac(C), returning [P-Q]; 2. A list of polynomials (a,b) such that `b^2 + h*b - f = 0 mod a`, returning [(a(x),y-b(x))]. EXAMPLES:: sage: P.<x> = PolynomialRing(QQ) sage: f = x^5 - x + 1; h = x sage: C = HyperellipticCurve(f,h,'u,v') sage: P = C(0,1,1) sage: J = C.jacobian() sage: Q = J(QQ)(P) sage: for i in range(6): i*Q (1) (u, v - 1) (u^2, v + u - 1) (u^2, v + 1) (u, v + 1) (1) :: sage: F.<a> = GF(3) sage: R.<x> = F[] sage: f = x^5-1 sage: C = HyperellipticCurve(f) sage: J = C.jacobian() sage: X = J(F) sage: a = x^2-x+1 sage: b = -x +1 sage: c = x-1 sage: d = 0 sage: D1 = X([a,b]) sage: D1 (x^2 + 2*x + 1, y + x + 2) sage: D2 = X([c,d]) sage: D2 (x + 2, y) sage: D1+D2 (x^2 + 2*x + 2, y + 2*x + 1) """ if isinstance(P, (int, long, Integer)) and P == 0: R = PolynomialRing(self.value_ring(), 'x') return JacobianMorphism_divisor_class_field(self, (R(1), R(0))) elif isinstance(P, (list, tuple)): if len(P) == 1 and P[0] == 0: R = PolynomialRing(self.value_ring(), 'x') return JacobianMorphism_divisor_class_field(self, (R(1), R(0))) elif len(P) == 2: P1 = P[0] P2 = P[1] if is_Integer(P1) and is_Integer(P2): R = PolynomialRing(self.value_ring(), 'x') P1 = R(P1) P2 = R(P2) return JacobianMorphism_divisor_class_field( self, tuple([P1, P2])) if is_Integer(P1) and is_Polynomial(P2): R = PolynomialRing(self.value_ring(), 'x') P1 = R(P1) return JacobianMorphism_divisor_class_field( self, tuple([P1, P2])) if is_Integer(P2) and is_Polynomial(P1): R = PolynomialRing(self.value_ring(), 'x') P2 = R(P2) return JacobianMorphism_divisor_class_field( self, tuple([P1, P2])) if is_Polynomial(P1) and is_Polynomial(P2): return JacobianMorphism_divisor_class_field(self, tuple(P)) if is_SchemeMorphism(P1) and is_SchemeMorphism(P2): return self(P1) - self(P2) raise TypeError("Argument P (= %s) must have length 2." % P) elif isinstance( P, JacobianMorphism_divisor_class_field) and self == P.parent(): return P elif is_SchemeMorphism(P): x0 = P[0] y0 = P[1] R, x = PolynomialRing(self.value_ring(), 'x').objgen() return self((x - x0, R(y0))) raise TypeError( "Argument P (= %s) does not determine a divisor class" % P)
def to_cartesian(self, func, params=None): """ Returns a 3-tuple of functions, parameterized over ``params``, that represents the Cartesian coordinates of the value of ``func``. INPUT: - ``func`` - A function in this coordinate space. Corresponds to the independent variable. - ``params`` - The parameters of ``func``. Corresponds to the dependent variables. EXAMPLES:: sage: from sage.plot.plot3d.plot3d import _ArbitraryCoordinates sage: x, y, z = var('x y z') sage: T = _ArbitraryCoordinates((x + y, x - y, z), z,[x,y]) sage: f(x, y) = 2*x+y sage: T.to_cartesian(f, [x, y]) (x + y, x - y, 2*x + y) sage: [h(1,2) for h in T.to_cartesian(lambda x,y: 2*x+y)] [3.0, -1.0, 4.0] We try to return a function having the same variable names as the function passed in:: sage: from sage.plot.plot3d.plot3d import _ArbitraryCoordinates sage: x, y, z = var('x y z') sage: T = _ArbitraryCoordinates((x + y, x - y, z), z,[x,y]) sage: f(a, b) = 2*a+b sage: T.to_cartesian(f, [a, b]) (a + b, a - b, 2*a + b) sage: t1,t2,t3=T.to_cartesian(lambda a,b: 2*a+b) sage: import inspect sage: inspect.getargspec(t1) ArgSpec(args=['a', 'b'], varargs=None, keywords=None, defaults=None) sage: inspect.getargspec(t2) ArgSpec(args=['a', 'b'], varargs=None, keywords=None, defaults=None) sage: inspect.getargspec(t3) ArgSpec(args=['a', 'b'], varargs=None, keywords=None, defaults=None) sage: def g(a,b): return 2*a+b sage: t1,t2,t3=T.to_cartesian(g) sage: inspect.getargspec(t1) ArgSpec(args=['a', 'b'], varargs=None, keywords=None, defaults=None) sage: t1,t2,t3=T.to_cartesian(2*a+b) sage: inspect.getargspec(t1) ArgSpec(args=['a', 'b'], varargs=None, keywords=None, defaults=None) If we cannot guess the right parameter names, then the parameters are named `u` and `v`:: sage: from sage.plot.plot3d.plot3d import _ArbitraryCoordinates sage: x, y, z = var('x y z') sage: T = _ArbitraryCoordinates((x + y, x - y, z), z,[x,y]) sage: t1,t2,t3=T.to_cartesian(operator.add) sage: inspect.getargspec(t1) ArgSpec(args=['u', 'v'], varargs=None, keywords=None, defaults=None) sage: [h(1,2) for h in T.to_cartesian(operator.mul)] [3.0, -1.0, 2.0] sage: [h(u=1,v=2) for h in T.to_cartesian(operator.mul)] [3.0, -1.0, 2.0] The output of the function ``func`` is coerced to a float when it is evaluated if the function is something like a lambda or python callable. This takes care of situations like f returning a singleton numpy array, for example. sage: from numpy import array sage: v_phi=array([ 0., 1.57079637, 3.14159274, 4.71238911, 6.28318548]) sage: v_theta=array([ 0., 0.78539819, 1.57079637, 2.35619456, 3.14159274]) sage: m_r=array([[ 0.16763356, 0.25683223, 0.16649297, 0.10594339, 0.55282422], ....: [ 0.16763356, 0.19993708, 0.31403568, 0.47359696, 0.55282422], ....: [ 0.16763356, 0.25683223, 0.16649297, 0.10594339, 0.55282422], ....: [ 0.16763356, 0.19993708, 0.31403568, 0.47359696, 0.55282422], ....: [ 0.16763356, 0.25683223, 0.16649297, 0.10594339, 0.55282422]]) sage: import scipy.interpolate sage: f=scipy.interpolate.RectBivariateSpline(v_phi,v_theta,m_r) sage: spherical_plot3d(f,(0,2*pi),(0,pi)) Graphics3d Object """ from sage.symbolic.expression import is_Expression from sage.rings.real_mpfr import is_RealNumber from sage.rings.integer import is_Integer if params is not None and (is_Expression(func) or is_RealNumber(func) or is_Integer(func)): return self.transform( **{ self.dep_var: func, self.indep_vars[0]: params[0], self.indep_vars[1]: params[1] }) else: # func might be a lambda or a Python callable; this makes it slightly # more complex. import sage.symbolic.ring dep_var_dummy = sage.symbolic.ring.var(self.dep_var) indep_var_dummies = sage.symbolic.ring.var(','.join( self.indep_vars)) transformation = self.transform( **{ self.dep_var: dep_var_dummy, self.indep_vars[0]: indep_var_dummies[0], self.indep_vars[1]: indep_var_dummies[1] }) if params is None: if callable(func): params = _find_arguments_for_callable(func) if params is None: params = ['u', 'v'] else: raise ValueError("function is not callable") def subs_func(t): # We use eval so that the lambda function has the same # variable names as the original function ll = """lambda {x},{y}: t.subs({{ dep_var_dummy: float(func({x}, {y})), indep_var_dummies[0]: float({x}), indep_var_dummies[1]: float({y}) }})""".format(x=params[0], y=params[1]) return eval( ll, dict(t=t, func=func, dep_var_dummy=dep_var_dummy, indep_var_dummies=indep_var_dummies)) return [subs_func(_) for _ in transformation]
def __call__(self, P): r""" Returns a rational point P in the abstract Homset J(K), given: 0. A point P in J = Jac(C), returning P; 1. A point P on the curve C such that J = Jac(C), where C is an odd degree model, returning [P - oo]; 2. A pair of points (P, Q) on the curve C such that J = Jac(C), returning [P-Q]; 2. A list of polynomials (a,b) such that `b^2 + h*b - f = 0 mod a`, returning [(a(x),y-b(x))]. EXAMPLES:: sage: P.<x> = PolynomialRing(QQ) sage: f = x^5 - x + 1; h = x sage: C = HyperellipticCurve(f,h,'u,v') sage: P = C(0,1,1) sage: J = C.jacobian() sage: Q = J(QQ)(P) sage: for i in range(6): i*Q (1) (u, v - 1) (u^2, v + u - 1) (u^2, v + 1) (u, v + 1) (1) :: sage: F.<a> = GF(3) sage: R.<x> = F[] sage: f = x^5-1 sage: C = HyperellipticCurve(f) sage: J = C.jacobian() sage: X = J(F) sage: a = x^2-x+1 sage: b = -x +1 sage: c = x-1 sage: d = 0 sage: D1 = X([a,b]) sage: D1 (x^2 + 2*x + 1, y + x + 2) sage: D2 = X([c,d]) sage: D2 (x + 2, y) sage: D1+D2 (x^2 + 2*x + 2, y + 2*x + 1) """ if isinstance(P,(int,long,Integer)) and P == 0: R = PolynomialRing(self.value_ring(), 'x') return JacobianMorphism_divisor_class_field(self, (R(1),R(0))) elif isinstance(P,(list,tuple)): if len(P) == 1 and P[0] == 0: R = PolynomialRing(self.value_ring(), 'x') return JacobianMorphism_divisor_class_field(self, (R(1),R(0))) elif len(P) == 2: P1 = P[0] P2 = P[1] if is_Integer(P1) and is_Integer(P2): R = PolynomialRing(self.value_ring(), 'x') P1 = R(P1) P2 = R(P2) return JacobianMorphism_divisor_class_field(self, tuple([P1,P2])) if is_Integer(P1) and is_Polynomial(P2): R = PolynomialRing(self.value_ring(), 'x') P1 = R(P1) return JacobianMorphism_divisor_class_field(self, tuple([P1,P2])) if is_Integer(P2) and is_Polynomial(P1): R = PolynomialRing(self.value_ring(), 'x') P2 = R(P2) return JacobianMorphism_divisor_class_field(self, tuple([P1,P2])) if is_Polynomial(P1) and is_Polynomial(P2): return JacobianMorphism_divisor_class_field(self, tuple(P)) if is_SchemeMorphism(P1) and is_SchemeMorphism(P2): return self(P1) - self(P2) raise TypeError("Argument P (= %s) must have length 2."%P) elif isinstance(P,JacobianMorphism_divisor_class_field) and self == P.parent(): return P elif is_SchemeMorphism(P): x0 = P[0]; y0 = P[1] R, x = PolynomialRing(self.value_ring(), 'x').objgen() return self((x-x0,R(y0))) raise TypeError("Argument P (= %s) does not determine a divisor class"%P)
def to_cartesian(self, func, params=None): """ Returns a 3-tuple of functions, parameterized over ``params``, that represents the Cartesian coordinates of the value of ``func``. INPUT: - ``func`` - A function in this coordinate space. Corresponds to the independent variable. - ``params`` - The parameters of func. Corresponds to the dependent variables. EXAMPLE:: sage: from sage.plot.plot3d.plot3d import _ArbitraryCoordinates sage: x, y, z = var('x y z') sage: T = _ArbitraryCoordinates((x + y, x - y, z), z,[x,y]) sage: f(x, y) = 2*x+y sage: T.to_cartesian(f, [x, y]) (x + y, x - y, 2*x + y) sage: [h(1,2) for h in T.to_cartesian(lambda x,y: 2*x+y)] [3.0, -1.0, 4.0] We try to return a function having the same variable names as the function passed in:: sage: from sage.plot.plot3d.plot3d import _ArbitraryCoordinates sage: x, y, z = var('x y z') sage: T = _ArbitraryCoordinates((x + y, x - y, z), z,[x,y]) sage: f(a, b) = 2*a+b sage: T.to_cartesian(f, [a, b]) (a + b, a - b, 2*a + b) sage: t1,t2,t3=T.to_cartesian(lambda a,b: 2*a+b) sage: import inspect sage: inspect.getargspec(t1) ArgSpec(args=['a', 'b'], varargs=None, keywords=None, defaults=None) sage: inspect.getargspec(t2) ArgSpec(args=['a', 'b'], varargs=None, keywords=None, defaults=None) sage: inspect.getargspec(t3) ArgSpec(args=['a', 'b'], varargs=None, keywords=None, defaults=None) sage: def g(a,b): return 2*a+b sage: t1,t2,t3=T.to_cartesian(g) sage: inspect.getargspec(t1) ArgSpec(args=['a', 'b'], varargs=None, keywords=None, defaults=None) sage: t1,t2,t3=T.to_cartesian(2*a+b) sage: inspect.getargspec(t1) ArgSpec(args=['a', 'b'], varargs=None, keywords=None, defaults=None) If we cannot guess the right parameter names, then the parameters are named `u` and `v`:: sage: from sage.plot.plot3d.plot3d import _ArbitraryCoordinates sage: x, y, z = var('x y z') sage: T = _ArbitraryCoordinates((x + y, x - y, z), z,[x,y]) sage: t1,t2,t3=T.to_cartesian(operator.add) sage: inspect.getargspec(t1) ArgSpec(args=['u', 'v'], varargs=None, keywords=None, defaults=None) sage: [h(1,2) for h in T.to_cartesian(operator.mul)] [3.0, -1.0, 2.0] sage: [h(u=1,v=2) for h in T.to_cartesian(operator.mul)] [3.0, -1.0, 2.0] The output of the function `func` is coerced to a float when it is evaluated if the function is something like a lambda or python callable. This takes care of situations like f returning a singleton numpy array, for example. sage: from numpy import array sage: v_phi=array([ 0., 1.57079637, 3.14159274, 4.71238911, 6.28318548]) sage: v_theta=array([ 0., 0.78539819, 1.57079637, 2.35619456, 3.14159274]) sage: m_r=array([[ 0.16763356, 0.25683223, 0.16649297, 0.10594339, 0.55282422], ... [ 0.16763356, 0.19993708, 0.31403568, 0.47359696, 0.55282422], ... [ 0.16763356, 0.25683223, 0.16649297, 0.10594339, 0.55282422], ... [ 0.16763356, 0.19993708, 0.31403568, 0.47359696, 0.55282422], ... [ 0.16763356, 0.25683223, 0.16649297, 0.10594339, 0.55282422]]) sage: import scipy.interpolate sage: f=scipy.interpolate.RectBivariateSpline(v_phi,v_theta,m_r) sage: spherical_plot3d(f,(0,2*pi),(0,pi)) Graphics3d Object """ from sage.symbolic.expression import is_Expression from sage.rings.real_mpfr import is_RealNumber from sage.rings.integer import is_Integer if params is not None and (is_Expression(func) or is_RealNumber(func) or is_Integer(func)): return self.transform(**{ self.dep_var: func, self.indep_vars[0]: params[0], self.indep_vars[1]: params[1] }) else: # func might be a lambda or a Python callable; this makes it slightly # more complex. import sage.symbolic.ring dep_var_dummy = sage.symbolic.ring.var(self.dep_var) indep_var_dummies = sage.symbolic.ring.var(','.join(self.indep_vars)) transformation = self.transform(**{ self.dep_var: dep_var_dummy, self.indep_vars[0]: indep_var_dummies[0], self.indep_vars[1]: indep_var_dummies[1] }) if params is None: if callable(func): params = _find_arguments_for_callable(func) if params is None: params=['u','v'] else: raise ValueError("function is not callable") def subs_func(t): # We use eval so that the lambda function has the same # variable names as the original function ll="""lambda {x},{y}: t.subs({{ dep_var_dummy: float(func({x}, {y})), indep_var_dummies[0]: float({x}), indep_var_dummies[1]: float({y}) }})""".format(x=params[0], y=params[1]) return eval(ll,dict(t=t, func=func, dep_var_dummy=dep_var_dummy, indep_var_dummies=indep_var_dummies)) return [subs_func(_) for _ in transformation]
def Polyhedron(vertices=None, rays=None, lines=None, ieqs=None, eqns=None, ambient_dim=None, base_ring=None, minimize=True, verbose=False, backend=None): """ Construct a polyhedron object. You may either define it with vertex/ray/line or inequalities/equations data, but not both. Redundant data will automatically be removed (unless ``minimize=False``), and the complementary representation will be computed. INPUT: - ``vertices`` -- list of point. Each point can be specified as any iterable container of ``base_ring`` elements. If ``rays`` or ``lines`` are specified but no ``vertices``, the origin is taken to be the single vertex. - ``rays`` -- list of rays. Each ray can be specified as any iterable container of ``base_ring`` elements. - ``lines`` -- list of lines. Each line can be specified as any iterable container of ``base_ring`` elements. - ``ieqs`` -- list of inequalities. Each line can be specified as any iterable container of ``base_ring`` elements. An entry equal to ``[-1,7,3,4]`` represents the inequality `7x_1+3x_2+4x_3\geq 1`. - ``eqns`` -- list of equalities. Each line can be specified as any iterable container of ``base_ring`` elements. An entry equal to ``[-1,7,3,4]`` represents the equality `7x_1+3x_2+4x_3= 1`. - ``base_ring`` -- either ``QQ`` or ``RDF``. The field over which the polyhedron will be defined. For ``QQ``, exact arithmetic will be used. For ``RDF``, floating point numbers will be used. Floating point arithmetic is faster but might give the wrong result for degenerate input. - ``ambient_dim`` -- integer. The ambient space dimension. Usually can be figured out automatically from the H/Vrepresentation dimensions. - ``backend`` -- string or ``None`` (default). The backend to use. Valid choices are * ``'cdd'``: use cdd (:mod:`~sage.geometry.polyhedron.backend_cdd`) with `\QQ` or `\RDF` coefficients depending on ``base_ring``. * ``'ppl'``: use ppl (:mod:`~sage.geometry.polyhedron.backend_ppl`) with `\ZZ` or `\QQ` coefficients depending on ``base_ring``. Some backends support further optional arguments: - ``minimize`` -- boolean (default: ``True``). Whether to immediately remove redundant H/V-representation data. Currently not used. - ``verbose`` -- boolean (default: ``False``). Whether to print verbose output for debugging purposes. Only supported by the cdd backends. OUTPUT: The polyhedron defined by the input data. EXAMPLES: Construct some polyhedra:: sage: square_from_vertices = Polyhedron(vertices = [[1, 1], [1, -1], [-1, 1], [-1, -1]]) sage: square_from_ieqs = Polyhedron(ieqs = [[1, 0, 1], [1, 1, 0], [1, 0, -1], [1, -1, 0]]) sage: list(square_from_ieqs.vertex_generator()) [A vertex at (1, -1), A vertex at (1, 1), A vertex at (-1, 1), A vertex at (-1, -1)] sage: list(square_from_vertices.inequality_generator()) [An inequality (1, 0) x + 1 >= 0, An inequality (0, 1) x + 1 >= 0, An inequality (-1, 0) x + 1 >= 0, An inequality (0, -1) x + 1 >= 0] sage: p = Polyhedron(vertices = [[1.1, 2.2], [3.3, 4.4]], base_ring=RDF) sage: p.n_inequalities() 2 The same polyhedron given in two ways:: sage: p = Polyhedron(ieqs = [[0,1,0,0],[0,0,1,0]]) sage: p.Vrepresentation() (A line in the direction (0, 0, 1), A ray in the direction (1, 0, 0), A ray in the direction (0, 1, 0), A vertex at (0, 0, 0)) sage: q = Polyhedron(vertices=[[0,0,0]], rays=[[1,0,0],[0,1,0]], lines=[[0,0,1]]) sage: q.Hrepresentation() (An inequality (1, 0, 0) x + 0 >= 0, An inequality (0, 1, 0) x + 0 >= 0) Finally, a more complicated example. Take `\mathbb{R}_{\geq 0}^6` with coordinates `a, b, \dots, f` and * The inequality `e+b \geq c+d` * The inequality `e+c \geq b+d` * The equation `a+b+c+d+e+f = 31` :: sage: positive_coords = Polyhedron(ieqs=[ ... [0, 1, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0], ... [0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 1]]) sage: P = Polyhedron(ieqs=positive_coords.inequalities() + ( ... [0,0,1,-1,-1,1,0], [0,0,-1,1,-1,1,0]), eqns=[[-31,1,1,1,1,1,1]]) sage: P A 5-dimensional polyhedron in QQ^6 defined as the convex hull of 7 vertices sage: P.dim() 5 sage: P.Vrepresentation() (A vertex at (31, 0, 0, 0, 0, 0), A vertex at (0, 0, 0, 0, 0, 31), A vertex at (0, 0, 0, 0, 31, 0), A vertex at (0, 0, 31/2, 0, 31/2, 0), A vertex at (0, 31/2, 31/2, 0, 0, 0), A vertex at (0, 31/2, 0, 0, 31/2, 0), A vertex at (0, 0, 0, 31/2, 31/2, 0)) .. NOTE:: * Once constructed, a ``Polyhedron`` object is immutable. * Although the option ``field=RDF`` allows numerical data to be used, it might not give the right answer for degenerate input data - the results can depend upon the tolerance setting of cdd. """ # Clean up the arguments vertices = _make_listlist(vertices) rays = _make_listlist(rays) lines = _make_listlist(lines) ieqs = _make_listlist(ieqs) eqns = _make_listlist(eqns) got_Vrep = (len(vertices+rays+lines) > 0) got_Hrep = (len(ieqs+eqns) > 0) if got_Vrep and got_Hrep: raise ValueError('You cannot specify both H- and V-representation.') elif got_Vrep: deduced_ambient_dim = _common_length_of(vertices, rays, lines)[1] elif got_Hrep: deduced_ambient_dim = _common_length_of(ieqs, eqns)[1] - 1 else: if ambient_dim is None: deduced_ambient_dim = 0 else: deduced_ambient_dim = ambient_dim if base_ring is None: base_ring = ZZ # set ambient_dim if ambient_dim is not None and deduced_ambient_dim!=ambient_dim: raise ValueError('Ambient space dimension mismatch. Try removing the "ambient_dim" parameter.') ambient_dim = deduced_ambient_dim # figure out base_ring from sage.misc.flatten import flatten values = flatten(vertices+rays+lines+ieqs+eqns) if base_ring is not None: try: convert = not all(x.parent() is base_ring for x in values) except AttributeError: # No x.parent() method? convert = True else: from sage.rings.integer import is_Integer from sage.rings.rational import is_Rational from sage.rings.real_double import is_RealDoubleElement if all(is_Integer(x) for x in values): if got_Vrep: base_ring = ZZ else: # integral inequalities usually do not determine a latice polytope! base_ring = QQ convert=False elif all(is_Rational(x) for x in values): base_ring = QQ convert=False elif all(is_RealDoubleElement(x) for x in values): base_ring = RDF convert=False else: try: map(ZZ, values) if got_Vrep: base_ring = ZZ else: base_ring = QQ convert = True except TypeError: from sage.structure.sequence import Sequence values = Sequence(values) if QQ.has_coerce_map_from(values.universe()): base_ring = QQ convert = True else: base_ring = RDF convert = True # Add the origin if necesarry if got_Vrep and len(vertices)==0: vertices = [ [0]*ambient_dim ] # Specific backends can override the base_ring from sage.geometry.polyhedron.parent import Polyhedra parent = Polyhedra(base_ring, ambient_dim, backend=backend) base_ring = parent.base_ring() # Convert into base_ring if necessary def convert_base_ring(lstlst): return [ [base_ring(x) for x in lst] for lst in lstlst] Hrep = Vrep = None if got_Hrep: Hrep = [ieqs, eqns] if got_Vrep: Vrep = [vertices, rays, lines] # finally, construct the Polyhedron return parent(Vrep, Hrep, convert=convert)
def to_cartesian(self, func, params=None): """ Returns a 3-tuple of functions, parameterized over ``params``, that represents the cartesian coordinates of the value of ``func``. INPUT: - ``func`` - A function in this coordinate space. Corresponds to the independent variable. - ``params`` - The parameters of func. Corresponds to the dependent variables. EXAMPLE:: sage: from sage.plot.plot3d.plot3d import _ArbitraryCoordinates sage: x, y, z = var('x y z') sage: T = _ArbitraryCoordinates((x + y, x - y, z), z,[x,y]) sage: f(x, y) = 2*x+y sage: T.to_cartesian(f, [x, y]) (x + y, x - y, 2*x + y) sage: [h(1,2) for h in T.to_cartesian(lambda x,y: 2*x+y)] [3, -1, 4] We try to return a function having the same variable names as the function passed in:: sage: from sage.plot.plot3d.plot3d import _ArbitraryCoordinates sage: x, y, z = var('x y z') sage: T = _ArbitraryCoordinates((x + y, x - y, z), z,[x,y]) sage: f(a, b) = 2*a+b sage: T.to_cartesian(f, [a, b]) (a + b, a - b, 2*a + b) sage: t1,t2,t3=T.to_cartesian(lambda a,b: 2*a+b) sage: import inspect sage: inspect.getargspec(t1) ArgSpec(args=['a', 'b'], varargs=None, keywords=None, defaults=None) sage: inspect.getargspec(t2) ArgSpec(args=['a', 'b'], varargs=None, keywords=None, defaults=None) sage: inspect.getargspec(t3) ArgSpec(args=['a', 'b'], varargs=None, keywords=None, defaults=None) sage: def g(a,b): return 2*a+b sage: t1,t2,t3=T.to_cartesian(g) sage: inspect.getargspec(t1) ArgSpec(args=['a', 'b'], varargs=None, keywords=None, defaults=None) sage: t1,t2,t3=T.to_cartesian(2*a+b) sage: inspect.getargspec(t1) ArgSpec(args=['a', 'b'], varargs=None, keywords=None, defaults=None) If we cannot guess the right parameter names, then the parameters are named `u` and `v`:: sage: from sage.plot.plot3d.plot3d import _ArbitraryCoordinates sage: x, y, z = var('x y z') sage: T = _ArbitraryCoordinates((x + y, x - y, z), z,[x,y]) sage: t1,t2,t3=T.to_cartesian(operator.add) sage: inspect.getargspec(t1) ArgSpec(args=['u', 'v'], varargs=None, keywords=None, defaults=None) sage: [h(1,2) for h in T.to_cartesian(operator.mul)] [3, -1, 2] sage: [h(u=1,v=2) for h in T.to_cartesian(operator.mul)] [3, -1, 2] """ from sage.symbolic.expression import is_Expression from sage.rings.real_mpfr import is_RealNumber from sage.rings.integer import is_Integer if params is not None and (is_Expression(func) or is_RealNumber(func) or is_Integer(func)): return self.transform(**{ self.dep_var: func, self.indep_vars[0]: params[0], self.indep_vars[1]: params[1] }) else: # func might be a lambda or a Python callable; this makes it slightly # more complex. import sage.symbolic.ring dep_var_dummy = sage.symbolic.ring.var(self.dep_var) indep_var_dummies = sage.symbolic.ring.var(','.join(self.indep_vars)) transformation = self.transform(**{ self.dep_var: dep_var_dummy, self.indep_vars[0]: indep_var_dummies[0], self.indep_vars[1]: indep_var_dummies[1] }) if params is None: if callable(func): params = _find_arguments_for_callable(func) if params is None: params=['u','v'] else: raise ValueError, "function is not callable" def subs_func(t): # We use eval so that the lambda function has the same # variable names as the original function ll="""lambda {x},{y}: t.subs({{ dep_var_dummy: func({x}, {y}), indep_var_dummies[0]: {x}, indep_var_dummies[1]: {y} }})""".format(x=params[0], y=params[1]) return eval(ll,dict(t=t, func=func, dep_var_dummy=dep_var_dummy, indep_var_dummies=indep_var_dummies)) return map(subs_func, transformation)