def fixed_point_set(self): #UHP
        r"""
        Return the a list or geodesic containing the fixed point set of
        orientation-preserving isometries.

        OUTPUT:

        - a list of hyperbolic points or a hyperbolic geodesic

        EXAMPLES::

            sage: UHP = HyperbolicPlane().UHP()
            sage: H = UHP.get_isometry(matrix(2, [-2/3,-1/3,-1/3,-2/3]))
            sage: g = H.fixed_point_set(); g
            Geodesic in UHP from -1 to 1
            sage: H(g.start()) == g.start()
            True
            sage: H(g.end()) == g.end()
            True
            sage: A = UHP.get_isometry(matrix(2,[0,1,1,0]))
            sage: A.preserves_orientation()
            False
            sage: A.fixed_point_set()
            Geodesic in UHP from 1 to -1

       ::

            sage: B = UHP.get_isometry(identity_matrix(2))
            sage: B.fixed_point_set()
            Traceback (most recent call last):
            ...
            ValueError: the identity transformation fixes the entire hyperbolic plane
        """
        d = sqrt(self._matrix.det() ** 2)
        M = self._matrix / sqrt(d)
        tau = M.trace() ** 2
        M_cls = self.classification()
        if M_cls == 'identity':
            raise ValueError("the identity transformation fixes the entire "
                             "hyperbolic plane")

        pt = self.domain().get_point
        if M_cls == 'parabolic':
            if abs(M[1, 0]) < EPSILON:
                return [pt(infinity)]
            else:
                # boundary point
                return [pt((M[0,0] - M[1,1]) / (2*M[1,0]))]
        elif M_cls == 'elliptic':
            d = sqrt(tau - 4)
            return [pt((M[0,0] - M[1,1] + sign(M[1,0])*d) / (2*M[1,0]))]
        elif M_cls == 'hyperbolic':
            if M[1,0] != 0: #if the isometry doesn't fix infinity
                d = sqrt(tau - 4)
                p_1 = (M[0,0] - M[1,1]+d) / (2*M[1,0])
                p_2 = (M[0,0] - M[1,1]-d) / (2*M[1,0])
                return self.domain().get_geodesic(pt(p_1), pt(p_2))
            #else, it fixes infinity.
            p_1 = M[0,1] / (M[1,1] - M[0,0])
            p_2 = infinity
            return self.domain().get_geodesic(pt(p_1), pt(p_2))

        try:
            p, q = [M.eigenvectors_right()[k][1][0] for k in range(2)]
        except IndexError:
            M = M.change_ring(RDF)
            p, q = [M.eigenvectors_right()[k][1][0] for k in range(2)]

        pts = []
        if p[1] == 0:
            pts.append(infinity)
        else:
            p = p[0] / p[1]
            if imag(p) >= 0:
                pts.append(p)
        if q[1] == 0:
            pts.append(infinity)
        else:
            q = q[0] / q[1]
            if imag(q) >= 0:
                pts.append(q)
        pts = [pt(k) for k in pts]
        if len(pts) == 2:
            return self.domain().get_geodesic(*pts)
        return pts
示例#2
0
    def fixed_point_set(self):  #UHP
        r"""
        Return the a list or geodesic containing the fixed point set of
        orientation-preserving isometries.

        OUTPUT:

        - a list of hyperbolic points or a hyperbolic geodesic

        EXAMPLES::

            sage: UHP = HyperbolicPlane().UHP()
            sage: H = UHP.get_isometry(matrix(2, [-2/3,-1/3,-1/3,-2/3]))
            sage: g = H.fixed_point_set(); g
            Geodesic in UHP from -1 to 1
            sage: H(g.start()) == g.start()
            True
            sage: H(g.end()) == g.end()
            True
            sage: A = UHP.get_isometry(matrix(2,[0,1,1,0]))
            sage: A.preserves_orientation()
            False
            sage: A.fixed_point_set()
            Geodesic in UHP from 1 to -1

       ::

            sage: B = UHP.get_isometry(identity_matrix(2))
            sage: B.fixed_point_set()
            Traceback (most recent call last):
            ...
            ValueError: the identity transformation fixes the entire hyperbolic plane
        """
        d = sqrt(self._matrix.det()**2)
        M = self._matrix / sqrt(d)
        tau = M.trace()**2
        M_cls = self.classification()
        if M_cls == 'identity':
            raise ValueError("the identity transformation fixes the entire "
                             "hyperbolic plane")

        pt = self.domain().get_point
        if M_cls == 'parabolic':
            if abs(M[1, 0]) < EPSILON:
                return [pt(infinity)]
            else:
                # boundary point
                return [pt((M[0, 0] - M[1, 1]) / (2 * M[1, 0]))]
        elif M_cls == 'elliptic':
            d = sqrt(tau - 4)
            return [
                pt((M[0, 0] - M[1, 1] + sign(M[1, 0]) * d) / (2 * M[1, 0]))
            ]
        elif M_cls == 'hyperbolic':
            if M[1, 0] != 0:  #if the isometry doesn't fix infinity
                d = sqrt(tau - 4)
                p_1 = (M[0, 0] - M[1, 1] + d) / (2 * M[1, 0])
                p_2 = (M[0, 0] - M[1, 1] - d) / (2 * M[1, 0])
                return self.domain().get_geodesic(pt(p_1), pt(p_2))
            #else, it fixes infinity.
            p_1 = M[0, 1] / (M[1, 1] - M[0, 0])
            p_2 = infinity
            return self.domain().get_geodesic(pt(p_1), pt(p_2))

        try:
            p, q = [M.eigenvectors_right()[k][1][0] for k in range(2)]
        except IndexError:
            M = M.change_ring(RDF)
            p, q = [M.eigenvectors_right()[k][1][0] for k in range(2)]

        pts = []
        if p[1] == 0:
            pts.append(infinity)
        else:
            p = p[0] / p[1]
            if imag(p) >= 0:
                pts.append(p)
        if q[1] == 0:
            pts.append(infinity)
        else:
            q = q[0] / q[1]
            if imag(q) >= 0:
                pts.append(q)
        pts = [pt(k) for k in pts]
        if len(pts) == 2:
            return self.domain().get_geodesic(*pts)
        return pts