def retr(self, X, U, mode="default"): if mode == "exp": return self.exp(X, U) elif mode == "qr": YR, YI = frac(X + U) Q, R = tensor.nlinalg.qr(YR + 1j * YI) Y = tensor.stack([Q.real, Q.imag]) return Y elif mode == "svd": YR, YI = frac(X + U) U, S, V = tensor.nlinalg.svd(YR + 1j * YI, full_matrices=False) Y = U.dot(tensor.eye(S.size)).dot(V) Y = tensor.stack([Y.real, Y.imag]) return Y elif mode == "cayley": A = complex_dot(hconj(U), X) + complex_dot(hconj(X), U) return complex_dot( complex_matrix_inverse(identity(self._n) + 0.5 * A), (identity(self._n) - 0.5 * A)) elif mode == "default": return self.retr(X, U, mode=self.retr_mode) else: raise ValueError( 'mode must equal to "svd", "qr", "exp" or "default", but "{}" is given' .format(mode))
def exp(self, X, U): # The exponential (in the sense of Lie group theory) of a tangent # vector U at X. first = self.concat([X, U], axis=1) XhU = complex_dot(hconj(X), U) second = complex_expm(self.concat([self.concat([XhU, -complex_dot(hconj(U), U)], 1), self.concat([identity(self._n), XhU], 1)], 0)) third = self.concat([complex_expm(-XhU), zeros((self._n, self._n))], 0) exponential = complex_dot(complex_dot(first, second), third) return exponential
def exp(self, X, U): # The exponential (in the sense of Lie group theory) of a tangent # vector U at X. first = self.concat([X, U], axis=1) XhU = complex_dot(hconj(X), U) second = complex_expm( self.concat([ self.concat([XhU, -complex_dot(hconj(U), U)], 1), self.concat([identity(self._n), XhU], 1) ], 0)) third = self.concat([complex_expm(-XhU), zeros((self._n, self._n))], 0) exponential = complex_dot(complex_dot(first, second), third) return exponential
def ehess2rhess(self, X, egrad, ehess, H): XHG = complex_dot(hconj(X), egrad) #XHG = X.conj().dot(egrad) herXHG = self.herm(XHG) HherXHG = complex_dot(H, herXHG) rhess = self.proj(X, ehess - HherXHG) return rhess
def ehess2rhess(self, X, egrad, ehess, H): # TODO implement this for future XHG = complex_dot(hconj(X), egrad) #XHG = X.conj().dot(egrad) herXHG = self.herm(XHG) HherXHG = complex_dot(H, herXHG) rhess = self.proj(X, ehess - HherXHG) return rhess
def retr(self, X, U, mode="default"): if mode == "exp": return self.exp(X, U) elif mode == "qr": YR, YI = frac(X + U) Q, R = tensor.nlinalg.qr(YR + 1j * YI) Y = tensor.stack([Q.real, Q.imag]) return Y elif mode == "svd": YR, YI = frac(X + U) U, S, V = tensor.nlinalg.svd(YR + 1j * YI, full_matrices=False) Y = U.dot(tensor.eye(S.size)).dot(V) Y = tensor.stack([Y.real, Y.imag]) return Y elif mode == "cayley": A = complex_dot(hconj(U), X) + complex_dot(hconj(X), U) return complex_dot(complex_matrix_inverse(identity(self._n) + 0.5 * A), (identity(self._n) - 0.5 * A)) elif mode == "default": return self.retr(X, U, mode=self.retr_mode) else: raise ValueError('mode must equal to "svd", "qr", "exp" or "default", but "{}" is given'.format(mode))
def herm(self, X): Xman = skew_hermitian_expm(X) XH = hconj(Xman) return 0.5 * (Xman + XH)
def proj(self, X, U): XHU = complex_dot(hconj(X), U) herXHU = self.herm(XHU) Up = U - complex_dot(X, herXHU) return Up
def herm(self, X): XH = hconj(X) return 0.5 * (X + XH)
def hconj(self, X): return tuple(hconj(x) for (manifold, x) in zip(self._manifolds, X))