Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect type of Real irrep as Complex irrep in C(n) and SO(2) #49

Open
Danfoa opened this issue May 18, 2023 · 4 comments
Open

Incorrect type of Real irrep as Complex irrep in C(n) and SO(2) #49

Danfoa opened this issue May 18, 2023 · 4 comments

Comments

@Danfoa
Copy link
Contributor

Danfoa commented May 18, 2023

In the function Group.irrep of both C(n) and SO(2) the convention of real Irreducible representations is used. However ever there is a mislabeling of the type of irreps as complex, which will create issues for applications where the distinction of real and complex irrep is necessary.

More precisely, irreducibles associated to rotations on the plane not aligned any coordinate axis, are constructed in:

# 2 dimensional Irreducible Representations
irrep = _build_irrep_cn(k)
character = _build_char_cn(k)
supported_nonlinearities = ['norm', 'gated']
self._irreps[id] = IrreducibleRepresentation(self, id, name, irrep, 2, 'C',
supported_nonlinearities=supported_nonlinearities,
character=character,
frequency=k)

# 2 dimensional Irreducible Representations
supported_nonlinearities = ['norm', 'gated']
self._irreps[id] = IrreducibleRepresentation(self, id, name, irrep, 2, 'C',
supported_nonlinearities=supported_nonlinearities,
character=character,
frequency=k)

As can be clearly seen from the comments and from the method group.utils.psi used to build the 2-dimensional representations:

def psi(theta: float, k: int = 1, gamma: float = 0.):
r"""
Rotation matrix corresponding to the angle :math:`k \theta + \gamma`.
"""
x = k * theta + gamma
c, s = np.cos(x), np.sin(x)
return np.array(([
[c, -s],
[s, c],
]))

These representations are Real rotation matrix representations. As it is known, any 2D rotation matrix is decomposable into two 1-dimensional Complex irreducible representations.

This brings several problems all emerging from the fact that you are labeling a complex representation as irreducible, when in fact it is decomposable. Beyond the trivial solution to the issue of changing the type of these irreps to Real, this issue points to a potential source of error in ESCNN by not having a method for actually checking if an irrep is in fact an irrep.

At least for complex irreducibles, this can be easily checked with:

def is_complex_irreducible(
    G: Group, representation: Union[Dict[GroupElement, np.ndarray], Callable[[GroupElement], np.ndarray]]
):
    """
    Check if a representation is complex irreducible. We check this by asserting weather non-scalar (no multiple of 
    identity ) Hermitian matrix `H` exists, such that `H` commutes with all group elements' representation.  
    If rho is irreducible, this function returns (True, H=I)  where I is the identity matrix.
    Otherwise, returns (False, H) where H is a non-scalar matrix that commutes with all elements' representation.
    """
    if isinstance(representation, dict):
        rep = lambda g: representation[g]
    else:
        rep = representation

    # Compute the dimension of the representation
    n = rep(G.sample()).shape[0]

    possible_transformations = []
    # Run through all r,s = 1,2,...,n
    for r in range(n):
        for s in range(n):
            # Define H_rs
            H_rs = np.zeros((n, n), dtype=complex)
            if r == s:
                H_rs[r, s] = 1
            elif r > s:
                H_rs[r, s] = 1
                H_rs[s, r] = 1
            else:  # r < s
                H_rs[r, s] = 1j
                H_rs[s, r] = -1j

            # Compute H
            H = sum([rep(g).conj().T @ H_rs @ rep(g) for g in G.elements]) / G.order()

            # If H is not a scalar matrix, then it is a matrix that commutes with all group actions.
            if not np.allclose(H[0, 0] * np.eye(H.shape[0]), H):
                return False, H
    # No Hermitian matrix was found to commute with all group actions. This is an irreducible rep
    return True, np.eye(n)

Let me know if this sounds like a good possible PR. I will contribute it gladly.

@Gabri95
Copy link
Collaborator

Gabri95 commented May 18, 2023

Hi @Danfoa

Thanks for the question!

Sorry for the confusion, but our library supports only real representations (so no complex valued irreps).
The label "R" or "C" does not refer to the field over which the representations are defined, but the "type" of the real irrep.
Indeed, real irreps of any compact group belong to one of three classes: real type, complex type or quaternionic type.

These are all real irreps and, depending on the class, they decompose into complex irreps in different ways.
For example, a complex-type irrep decomposes into two complex irreps, like in your SO(2) example, while real-type irreps do not decompose further into complex irreps.

An important property is that complex-type irreps are essentially equivalent to the "realification" of a complex irrep (e.g. the 2D rotaiton matrix is the realification of the 1-dim complex number), which allows you to "simulate" complex irreps by using real ones.

You can find more details about this in the appendix C of our paper.

Hope this helps!

Gabriele

@Danfoa
Copy link
Contributor Author

Danfoa commented May 19, 2023

Hi @Gabri95

I understand now. Do you think there is value in placing efforts into introducing support for complex representations? Considering that: (1) representation theory is simpler and commonly given over the complex field. (2) Some applications are more convenient with complex reps, (3) I bet a lot of people would be happy to have support for Complex irreps.

  • For instance, I am working with linear symmetrical dynamical systems, where I am required to do Isotypic Decomposition of a representation into its complex irreps, facilitating mode-decomposition, plotting of complex observations, and a general understanding of the dynamics. I expect this to have applications in both ML and dynamical systems theory.

I would assume this would be done by defining the appropriate mappings between complex and real irreducibles and exploiting all the machinery you have already built.

To motivate my argument, and probably get some guidance from your side. Consider that my biggest limitation in the use of the Representation class has been that in order to create an instance of a representation I need to know in advance the change of basis and the list of real-irreducibles. In practice what I have are:

  1. Somewhat large vector spaces.
  2. Knowledge of the symmetry group that the space has.
  3. Knowledge of the symmetry representations in that space for all group elements. These representations are not trivial combinations of real-irreps or of the regular rep. Therefore is not trivial to determine both Q and the real irrep list.

To solve this I have code for the Isotypic Decomposition of the "known" representations into their complex irreducibles. And I am now, trying to produce the matching between the group known real irreps, provided by ESCNN, and the empirical complex irreps, found through the Isotypic Decomposition. To my surprise, the mapping between complex and real irreps has been more challenging to solve than the actual Isotypic Decomposition, but once I solve this. I will be able to instanciate Representations solely by providing the callable/mapping of group elements with matrices.

@Gabri95
Copy link
Collaborator

Gabri95 commented May 31, 2023

Hi @Danfoa

Thanks for bringing this up.

I understand the need for an interface for the user to construct real representations from complex ones, but I am not convinced yet the library should support complex representations.

The key observation is that any complex representation must be implemented via its realification (i.e. storing the real and imaginary components as a 2-dimensional real number).
However, the realification of a complex irrep is either a real irrep or decomposes into real irreps; moreover, real irreps can have larger intertwiner spaces (i.e. they support more equivariant linear maps), with direct implications on the expressivity of an equivariant network, as we discussed in our first paper for SO(2).
Let me refer you again to the appendix C of our paper for more technical details.

Hence, I fear directly supporting complex irreps will lead users to mistakenly build suboptimal models.
Forcing the users to convert their complex representations into real representations should make them aware of this situation.

Still, I agree this conversion process should be more automated.
The best idea that comes to my mind now is leveraging the
decompose_representation_general method (which takes any representation implemented as a function Group -> Matrix and numerically decomposes it using the group's irreps).
This could be wrapped into a decompose_complex_representation method which 1) computes the realification of your complex representation and 2) uses decompose_representation_general to decompose it.

In this way, the user would still use only real representations but could create them more easily starting from complex ones.
Do you think this could solve your issue?

Best,
Gabriele

@HiperMaximus
Copy link

I don't know if it would be outside the scope of the library, but I'm interested in the Unitary group U(n), which (I think) would require a complex representation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants