Esempio n. 1
0
def get_id_minus_conjugate_z_times_z(z: torch.Tensor):
    """
    :param z: b x 2 x n x n
    :return: Id - \overline(z)z
    """
    identity = sm.identity_like(z)
    conj_z_z = sm.bmm(sm.conjugate(z), z)
    return sm.subtract(identity, conj_z_z)
Esempio n. 2
0
def inverse_cayley_transform(z: torch.Tensor) -> torch.Tensor:
    """
    T^-1(Z): Bounded Domain Model -> Upper Half Space model
    T^-1(Z) = i (Id + Z)(Id - Z)^-1

    :param z: b x 2 x n x n: PRE: z \in Bounded Domain Manifold
    :return: y \in Upper Half Space Manifold
    """
    identity = sm.identity_like(z)

    i_z_plus_id = sm.multiply_by_i(sm.add(identity, z))
    inv_z_minus_id = sm.inverse(sm.subtract(identity, z))

    return sm.bmm(i_z_plus_id, inv_z_minus_id)
Esempio n. 3
0
    def inner(self,
              z: torch.Tensor,
              u: torch.Tensor,
              v=None,
              *,
              keepdim=False) -> torch.Tensor:
        """
        Inner product for tangent vectors at point :math:`z`.
        For the bounded domain model, the inner product at point z of the vectors u, v
        it is (z, u, v are complex symmetric matrices):

        g_{z}(u, v) = tr[ (Id -  ẑz)^-1 u (Id - zẑ)^-1 \ov{v} ]

        :param z: torch.Tensor point on the manifold: b x 2 x n x n
        :param u: torch.Tensor tangent vector at point :math:`z`: b x 2 x n x n
        :param v: Optional[torch.Tensor] tangent vector at point :math:`z`: b x 2 x n x n
        :param keepdim: bool keep the last dim?
        :return: torch.Tensor inner product (broadcastable): b x 2 x 1 x 1
        """
        if v is None:
            v = u
        identity = sm.identity_like(z)
        conj_z = sm.conjugate(z)
        conj_z_z = sm.bmm(conj_z, z)
        z_conj_z = sm.bmm(z, conj_z)

        inv_id_minus_conj_z_z = sm.subtract(identity, conj_z_z)
        inv_id_minus_z_conj_z = sm.subtract(identity, z_conj_z)

        inv_id_minus_conj_z_z = sm.inverse(inv_id_minus_conj_z_z)
        inv_id_minus_z_conj_z = sm.inverse(inv_id_minus_z_conj_z)

        res = sm.bmm3(inv_id_minus_conj_z_z, u, inv_id_minus_z_conj_z)
        res = sm.bmm(res, sm.conjugate(v))
        real_part = sm.trace(sm.real(res), keepdim=True)
        real_part = torch.unsqueeze(real_part, -1)  # b x 1 x 1
        return sm.stick(real_part, real_part)  # # b x 2 x 1 x 1
Esempio n. 4
0
def cayley_transform(z: torch.Tensor) -> torch.Tensor:
    """
    T(Z): Upper Half Space model -> Bounded Domain Model
    T(Z) = (Z - i Id)(Z + i Id)^-1

    :param z: b x 2 x n x n: PRE: z \in Upper Half Space Manifold
    :return: y \in Bounded Domain Manifold
    """
    identity = sm.identity_like(z)
    i_identity = sm.stick(sm.imag(identity), sm.real(identity))

    z_minus_id = sm.subtract(z, i_identity)
    inv_z_plus_id = sm.inverse(sm.add(z, i_identity))

    return sm.bmm(z_minus_id, inv_z_plus_id)
Esempio n. 5
0
    def dist(self, w: torch.Tensor, x: torch.Tensor, *, keepdim=False) -> torch.Tensor:
        """
        Given  W, X in the compact dual:
            1 - TakagiFact(W) -> W = ÛPU*
            2 - U unitary, P diagonal, Û: U conjugate, U*: U conjugate transpose
            3 - Define A = (Id + P^2)^(-1/2)
            4 - Define M = [(A  -AP), (AP  A)] * [(U^t  0), (0  U)]
            5 - MW = 0 by construction. Y = MX implies
                Y = [(A  -AP), (AP  A)] * [(U^t  0), (0  U)] * X
                Y = [(A  -AP), (AP  A)] * U^tXU        Lets call Q = U^tXU
                Y = (AQ - AP) (APQ + A)^-1
            6 - TakagiFact(Y) = ŜDS*
            7 - Distance = sqrt[ sum ( arctan(d_k)^2 ) ]  with d_k the diagonal entries of D

        :param w, x: b x 2 x n x n: elements in the Compact Dual
        :param keepdim:
        :return: distance between w and x in the compact dual
        """
        p, u = self.takagi_factorization.factorize(w)  # p: b x n, u: b x 2 x n x n

        # Define A: since (Id + P^2) is diagonal, taking the matrix sqrt is just the sqrt of the entries
        # Moreover, then taking the inverse of that is taking the inverse of the entries.
        a = 1 + p**2
        a = 1 / torch.sqrt(a)
        a = sm.diag_embed(a)
        p = sm.diag_embed(p)

        q = sm.bmm3(sm.transpose(u), x, u)
        ap = sm.bmm(a, p)
        aq_minus_ap = sm.subtract(sm.bmm(a, q), ap)
        apq_plus_a_inv = sm.add(sm.bmm(ap, q), a)
        apq_plus_a_inv = sm.inverse(apq_plus_a_inv)
        y = sm.bmm(aq_minus_ap, apq_plus_a_inv)                     # b x 2 x n x n

        d, s = self.takagi_factorization.factorize(y)   # d = b x n

        d = torch.atan(d)
        dist = self.metric.compute_metric(d)
        return dist
Esempio n. 6
0
    def test_subtract(self):
        x = get_random_symmetric_matrices(10, 4)
        result = torch.zeros_like(x)

        self.assertAllEqual(result, sm.subtract(x, x))