def intersection(self, other): r""" The intersection of ``self`` with ``other``. INPUT: - ``other`` -- a hyperplane, a polyhedron, or something that defines a polyhedron OUTPUT: A polyhedron. EXAMPLES:: sage: H.<x,y,z> = HyperplaneArrangements(QQ) sage: h = x + y + z - 1 sage: h.intersection(x - y) A 1-dimensional polyhedron in QQ^3 defined as the convex hull of 1 vertex and 1 line sage: h.intersection(polytopes.cube()) A 2-dimensional polyhedron in QQ^3 defined as the convex hull of 3 vertices """ from sage.geometry.polyhedron.base import is_Polyhedron from sage.geometry.polyhedron.constructor import Polyhedron if not is_Polyhedron(other): try: other = other.polyhedron() except AttributeError: other = Polyhedron(other) return self.polyhedron().intersection(other)
def intersection(self, other): r""" The intersection of ``self`` with ``other``. INPUT: - ``other`` -- a hyperplane, a polyhedron, or something that defines a polyhedron OUTPUT: A polyhedron. EXAMPLES:: sage: H.<x,y,z> = HyperplaneArrangements(QQ) sage: h = x + y + z - 1 sage: h.intersection(x - y) A 1-dimensional polyhedron in QQ^3 defined as the convex hull of 1 vertex and 1 line sage: h.intersection(polytopes.n_cube(3)) A 2-dimensional polyhedron in QQ^3 defined as the convex hull of 3 vertices """ from sage.geometry.polyhedron.base import is_Polyhedron from sage.geometry.polyhedron.constructor import Polyhedron if not is_Polyhedron(other): try: other = other.polyhedron() except AttributeError: other = Polyhedron(other) return self.polyhedron().intersection(other)
def _element_constructor_(self, *args, **kwds): """ The element (polyhedron) constructor. INPUT: - ``Vrep`` -- a list `[vertices, rays, lines]`` or ``None``. - ``Hrep`` -- a list `[ieqs, eqns]`` or ``None``. - ``convert`` -- boolean keyword argument (default: ``True``). Whether to convert the cooordinates into the base ring. - ``**kwds`` -- optional remaining keywords that are passed to the polyhedron constructor. EXAMPLES:: sage: from sage.geometry.polyhedron.parent import Polyhedra sage: P = Polyhedra(QQ, 3) sage: P._element_constructor_([[(0,0,0),(1,0,0),(0,1,0),(0,0,1)], [], []], None) A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 4 vertices sage: P([[(0,0,0),(1,0,0),(0,1,0),(0,0,1)], [], []], None) A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 4 vertices sage: P(0) A 0-dimensional polyhedron in QQ^3 defined as the convex hull of 1 vertex """ nargs = len(args) convert = kwds.pop('convert', True) if nargs == 2: Vrep, Hrep = args def convert_base_ring(lstlst): return [[self.base_ring()(x) for x in lst] for lst in lstlst] if convert and Hrep: Hrep = [convert_base_ring(_) for _ in Hrep] if convert and Vrep: Vrep = [convert_base_ring(_) for _ in Vrep] return self.element_class(self, Vrep, Hrep, **kwds) if nargs == 1 and is_Polyhedron(args[0]): polyhedron = args[0] Hrep = [ polyhedron.inequality_generator(), polyhedron.equation_generator() ] return self.element_class(self, None, Hrep, **kwds) if nargs == 1 and args[0] == 0: return self.zero() raise ValueError('Cannot convert to polyhedron object.')
def _element_constructor_(self, *args, **kwds): """ The element (polyhedron) constructor. INPUT: - ``Vrep`` -- a list `[vertices, rays, lines]`` or ``None``. - ``Hrep`` -- a list `[ieqs, eqns]`` or ``None``. - ``convert`` -- boolean keyword argument (default: ``True``). Whether to convert the cooordinates into the base ring. - ``**kwds`` -- optional remaining keywords that are passed to the polyhedron constructor. EXAMPLES:: sage: from sage.geometry.polyhedron.parent import Polyhedra sage: P = Polyhedra(QQ, 3) sage: P._element_constructor_([[(0,0,0),(1,0,0),(0,1,0),(0,0,1)], [], []], None) A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 4 vertices sage: P([[(0,0,0),(1,0,0),(0,1,0),(0,0,1)], [], []], None) A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 4 vertices sage: P(0) A 0-dimensional polyhedron in QQ^3 defined as the convex hull of 1 vertex """ nargs = len(args) convert = kwds.pop("convert", True) if nargs == 2: Vrep, Hrep = args def convert_base_ring(lstlst): return [[self.base_ring()(x) for x in lst] for lst in lstlst] if convert and Hrep: Hrep = map(convert_base_ring, Hrep) if convert and Vrep: Vrep = map(convert_base_ring, Vrep) return self.element_class(self, Vrep, Hrep, **kwds) if nargs == 1 and is_Polyhedron(args[0]): polyhedron = args[0] Hrep = [polyhedron.inequality_generator(), polyhedron.equation_generator()] return self.element_class(self, None, Hrep, **kwds) if nargs == 1 and args[0] == 0: return self.zero_element() raise ValueError("Cannot convert to polyhedron object.")
def _element_constructor_(self, arg, sort_slopes=True, last_slope=Infinity): """ INPUT: - ``arg`` -- an argument describing the Newton polygon - ``sort_slopes`` -- boolean (default: ``True``). Specifying whether slopes must be first sorted - ``last_slope`` -- rational or infinity (default: ``Infinity``). The last slope of the Newton polygon The first argument ``arg`` can be either: - a polyhedron in `\QQ^2` - the element ``0`` (corresponding to the empty Newton polygon) - the element ``1`` (corresponding to the Newton polygon of the constant polynomial equal to 1) - a list/tuple/iterable of vertices - a list/tuple/iterable of slopes OUTPUT: The corresponding Newton polygon. For more informations, see :class:`ParentNewtonPolygon`. TESTS: sage: from sage.geometry.newton_polygon import NewtonPolygon sage: NewtonPolygon(0) Empty Newton polygon sage: NewtonPolygon(1) Finite Newton polygon with 1 vertex: (0, 0) """ if is_Polyhedron(arg): return self.element_class(arg, parent=self) if arg == 0: polyhedron = Polyhedron(base_ring=self.base_ring(), ambient_dim=2) return self.element_class(polyhedron, parent=self) if arg == 1: polyhedron = Polyhedron(base_ring=self.base_ring(), vertices=[(0, 0)], rays=[(0, 1)]) return self.element_class(polyhedron, parent=self) if not isinstance(arg, list): try: arg = list(arg) except TypeError: raise TypeError( "argument must be a list of coordinates or a list of (rational) slopes" ) if len(arg) > 0 and arg[0] in self.base_ring(): if sort_slopes: arg.sort() x = y = 0 vertices = [(x, y)] for slope in arg: if not slope in self.base_ring(): raise TypeError( "argument must be a list of coordinates or a list of (rational) slopes" ) x += 1 y += slope vertices.append((x, y)) else: vertices = [(x, y) for (x, y) in arg if y is not Infinity] if len(vertices) == 0: polyhedron = Polyhedron(base_ring=self.base_ring(), ambient_dim=2) else: rays = [(0, 1)] if last_slope is not Infinity: rays.append((1, last_slope)) polyhedron = Polyhedron(base_ring=self.base_ring(), vertices=vertices, rays=rays) return self.element_class(polyhedron, parent=self)
def _element_constructor_(self, *args, **kwds): """ The element (polyhedron) constructor. INPUT: - ``Vrep`` -- a list `[vertices, rays, lines]`` or ``None``. - ``Hrep`` -- a list `[ieqs, eqns]`` or ``None``. - ``convert`` -- boolean keyword argument (default: ``True``). Whether to convert the coordinates into the base ring. - ``**kwds`` -- optional remaining keywords that are passed to the polyhedron constructor. EXAMPLES:: sage: from sage.geometry.polyhedron.parent import Polyhedra sage: P = Polyhedra(QQ, 3) sage: P._element_constructor_([[(0, 0, 0), (1, 0, 0), (0, 1, 0), (0,0,1)], [], []], None) A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 4 vertices sage: P([[(0,0,0),(1,0,0),(0,1,0),(0,0,1)], [], []], None) A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 4 vertices sage: P(0) A 0-dimensional polyhedron in QQ^3 defined as the convex hull of 1 vertex Check that :trac:`21270` is fixed:: sage: poly = polytopes.regular_polygon(7) sage: lp, x = poly.to_linear_program(solver='InteractiveLP', return_variable=True) sage: lp.set_objective(x[0] + x[1]) sage: b = lp.get_backend() sage: P = b.interactive_lp_problem() sage: p = P.plot() sage: Q = Polyhedron(ieqs=[[-499999, 1000000], [1499999, -1000000]]) sage: P = Polyhedron(ieqs=[[0, 1.0], [1.0, -1.0]], base_ring=RDF) sage: Q.intersection(P) A 1-dimensional polyhedron in RDF^1 defined as the convex hull of 2 vertices sage: P.intersection(Q) A 1-dimensional polyhedron in RDF^1 defined as the convex hull of 2 vertices """ nargs = len(args) convert = kwds.pop('convert', True) def convert_base_ring(lstlst): return [[self.base_ring()(x) for x in lst] for lst in lstlst] # renormalize before converting when going from QQ to RDF, see trac 21270 def convert_base_ring_Hrep(lstlst): newlstlst = [] for lst in lstlst: if all(c in QQ for c in lst): m = max(abs(w) for w in lst) if m == 0: newlstlst.append(lst) else: newlstlst.append([q/m for q in lst]) else: newlstlst.append(lst) return convert_base_ring(newlstlst) if nargs == 2: Vrep, Hrep = args if convert and Hrep: if self.base_ring == RDF: Hrep = [convert_base_ring_Hrep(_) for _ in Hrep] else: Hrep = [convert_base_ring(_) for _ in Hrep] if convert and Vrep: Vrep = [convert_base_ring(_) for _ in Vrep] return self.element_class(self, Vrep, Hrep, **kwds) if nargs == 1 and is_Polyhedron(args[0]): polyhedron = args[0] return self._element_constructor_polyhedron(polyhedron, **kwds) if nargs == 1 and args[0] == 0: return self.zero() raise ValueError('Cannot convert to polyhedron object.')
def _element_constructor_(self, arg, sort_slopes=True, last_slope=Infinity): """ INPUT: - ``arg`` -- an argument describing the Newton polygon - ``sort_slopes`` -- boolean (default: ``True``). Specifying whether slopes must be first sorted - ``last_slope`` -- rational or infinity (default: ``Infinity``). The last slope of the Newton polygon The first argument ``arg`` can be either: - a polyhedron in `\QQ^2` - the element ``0`` (corresponding to the empty Newton polygon) - the element ``1`` (corresponding to the Newton polygon of the constant polynomial equal to 1) - a list/tuple/iterable of vertices - a list/tuple/iterable of slopes OUTPUT: The corresponding Newton polygon. For more informations, see :class:`ParentNewtonPolygon`. TESTS: sage: from sage.geometry.newton_polygon import NewtonPolygon sage: NewtonPolygon(0) Empty Newton polygon sage: NewtonPolygon(1) Finite Newton polygon with 1 vertex: (0, 0) """ if is_Polyhedron(arg): return self.element_class(arg, parent=self) if arg == 0: polyhedron = Polyhedron(base_ring=self.base_ring(), ambient_dim=2) return self.element_class(polyhedron, parent=self) if arg == 1: polyhedron = Polyhedron(base_ring=self.base_ring(), vertices=[(0,0)], rays=[(0,1)]) return self.element_class(polyhedron, parent=self) if not isinstance(arg, list): try: arg = list(arg) except TypeError: raise TypeError("argument must be a list of coordinates or a list of (rational) slopes") if len(arg) > 0 and arg[0] in self.base_ring(): if sort_slopes: arg.sort() x = y = 0 vertices = [(x, y)] for slope in arg: if not slope in self.base_ring(): raise TypeError("argument must be a list of coordinates or a list of (rational) slopes") x += 1 y += slope vertices.append((x,y)) else: vertices = [(x, y) for (x, y) in arg if y is not Infinity] if len(vertices) == 0: polyhedron = Polyhedron(base_ring=self.base_ring(), ambient_dim=2) else: rays = [(0, 1)] if last_slope is not Infinity: rays.append((1, last_slope)) polyhedron = Polyhedron(base_ring=self.base_ring(), vertices=vertices, rays=rays) return self.element_class(polyhedron, parent=self)
def _element_constructor_(self, *args, **kwds): """ The element (polyhedron) constructor. INPUT: - ``Vrep`` -- a list ``[vertices, rays, lines]`` or ``None``. - ``Hrep`` -- a list ``[ieqs, eqns]`` or ``None``. - ``convert`` -- boolean keyword argument (default: ``True``). Whether to convert the coordinates into the base ring. - ``**kwds`` -- optional remaining keywords that are passed to the polyhedron constructor. EXAMPLES:: sage: from sage.geometry.polyhedron.parent import Polyhedra sage: P = Polyhedra(QQ, 3) sage: P._element_constructor_([[(0, 0, 0), (1, 0, 0), (0, 1, 0), (0,0,1)], [], []], None) A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 4 vertices sage: P([[(0,0,0),(1,0,0),(0,1,0),(0,0,1)], [], []], None) A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 4 vertices sage: P(0) A 0-dimensional polyhedron in QQ^3 defined as the convex hull of 1 vertex Check that :trac:`21270` is fixed:: sage: poly = polytopes.regular_polygon(7) sage: lp, x = poly.to_linear_program(solver='InteractiveLP', return_variable=True) sage: lp.set_objective(x[0] + x[1]) sage: b = lp.get_backend() sage: P = b.interactive_lp_problem() sage: p = P.plot() # optional - sage.plot sage: Q = Polyhedron(ieqs=[[-499999, 1000000], [1499999, -1000000]]) sage: P = Polyhedron(ieqs=[[0, 1.0], [1.0, -1.0]], base_ring=RDF) sage: Q.intersection(P) A 1-dimensional polyhedron in RDF^1 defined as the convex hull of 2 vertices sage: P.intersection(Q) A 1-dimensional polyhedron in RDF^1 defined as the convex hull of 2 vertices The default is not to copy an object if the parent is ``self``:: sage: p = polytopes.cube(backend='field') sage: P = p.parent() sage: q = P._element_constructor_(p) sage: q is p True sage: r = P._element_constructor_(p, copy=True) sage: r is p False When the parent of the object is not ``self``, the default is not to copy:: sage: Q = P.base_extend(AA) sage: q = Q._element_constructor_(p) sage: q is p False sage: q = Q._element_constructor_(p, copy=False) Traceback (most recent call last): ... ValueError: you need to make a copy when changing the parent For mutable polyhedra either ``copy`` or ``mutable`` must be specified:: sage: p = Polyhedron(vertices=[[0, 1], [1, 0]], mutable=True) sage: P = p.parent() sage: q = P._element_constructor_(p) Traceback (most recent call last): ... ValueError: must make a copy to obtain immutable object from mutable input sage: q = P._element_constructor_(p, mutable=True) sage: q is p True sage: r = P._element_constructor_(p, copy=True) sage: r.is_mutable() False sage: r is p False """ nargs = len(args) convert = kwds.pop('convert', True) def convert_base_ring(lstlst): return [[self.base_ring()(x) for x in lst] for lst in lstlst] # renormalize before converting when going from QQ to RDF, see trac 21270 def convert_base_ring_Hrep(lstlst): newlstlst = [] for lst in lstlst: if all(c in QQ for c in lst): m = max(abs(w) for w in lst) if m == 0: newlstlst.append(lst) else: newlstlst.append([q / m for q in lst]) else: newlstlst.append(lst) return convert_base_ring(newlstlst) if nargs == 2: Vrep, Hrep = args if convert and Hrep: if self.base_ring == RDF: Hrep = [convert_base_ring_Hrep(_) for _ in Hrep] else: Hrep = [convert_base_ring(_) for _ in Hrep] if convert and Vrep: Vrep = [convert_base_ring(_) for _ in Vrep] return self.element_class(self, Vrep, Hrep, **kwds) if nargs == 1 and is_Polyhedron(args[0]): copy = kwds.pop('copy', args[0].parent() is not self) mutable = kwds.pop('mutable', False) if not copy and args[0].parent() is not self: raise ValueError( "you need to make a copy when changing the parent") if args[0].is_mutable() and not copy and not mutable: raise ValueError( "must make a copy to obtain immutable object from mutable input" ) if not copy and mutable is args[0].is_mutable(): return args[0] polyhedron = args[0] return self._element_constructor_polyhedron(polyhedron, mutable=mutable, **kwds) if nargs == 1 and args[0] == 0: return self.zero() raise ValueError('Cannot convert to polyhedron object.')
def __call__(self, v): """ Apply the affine transformation to ``v``. INPUT: - ``v`` -- a polynomial, a multivariate polynomial, a polyhedron, a vector, or anything that can be converted into a vector. OUTPUT: The image of ``v`` under the affine group element. EXAMPLES:: sage: G = AffineGroup(2, QQ) sage: g = G([0,1,-1,0],[2,3]); g [ 0 1] [2] x |-> [-1 0] x + [3] sage: v = vector([4,5]) sage: g(v) (7, -1) sage: R.<x,y> = QQ[] sage: g(x), g(y) (y + 2, -x + 3) sage: p = x^2 + 2*x*y + y + 1 sage: g(p) -2*x*y + y^2 - 5*x + 10*y + 20 The action on polynomials is such that it intertwines with evaluation. That is:: sage: p(*g(v)) == g(p)(*v) True Test that the univariate polynomial ring is covered:: sage: H = AffineGroup(1, QQ) sage: h = H([2],[3]); h x |-> [2] x + [3] sage: R.<z> = QQ[] sage: h(z+1) 3*z + 2 The action on a polyhedron is defined (see :trac:`30327`):: sage: F = AffineGroup(3, QQ) sage: M = matrix(3, [-1, -2, 0, 0, 0, 1, -2, 1, -1]) sage: v = vector(QQ,(1,2,3)) sage: f = F(M, v) sage: cube = polytopes.cube() sage: f(cube) A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 8 vertices """ parent = self.parent() # start with the most probable case, i.e., v is in the vector space if v in parent.vector_space(): return self._A*v + self._b from sage.rings.polynomial.polynomial_element import is_Polynomial if is_Polynomial(v) and parent.degree() == 1: ring = v.parent() return ring([self._A[0,0], self._b[0]]) from sage.rings.polynomial.multi_polynomial import is_MPolynomial if is_MPolynomial(v) and parent.degree() == v.parent().ngens(): ring = v.parent() from sage.modules.all import vector image_coords = self._A * vector(ring, ring.gens()) + self._b return v(*image_coords) from sage.geometry.polyhedron.base import is_Polyhedron if is_Polyhedron(v): return self._A*v + self._b # otherwise, coerce v into the vector space v = parent.vector_space()(v) return self._A*v + self._b