Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions .github/workflows/UnitTest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ on:
branches:
- main
pull_request:
schedule:
- cron: '20 00 1 * *'
branches:
- main

jobs:
test:
Expand All @@ -17,19 +17,19 @@ jobs:
fail-fast: false
matrix:
julia-version:
- '1.6' # Replace this with the minimum Julia version that your package supports. E.g. if your package requires Julia 1.5 or higher, change this to '1.5'.
- '1' # Leave this line unchanged. '1' will automatically expand to the latest stable 1.x release of Julia.
- 'nightly'
- "1.9" # Replace this with the minimum Julia version that your package supports. E.g. if your package requires Julia 1.5 or higher, change this to '1.5'.
- "1" # Leave this line unchanged. '1' will automatically expand to the latest stable 1.x release of Julia.
- "nightly"
os:
- ubuntu-latest
arch:
- x64
include:
- os: windows-latest
julia-version: '1'
julia-version: "1"
arch: x64
- os: macOS-latest
julia-version: '1'
julia-version: "1"
arch: x64
env:
PYTHON: ""
Expand Down
6 changes: 3 additions & 3 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
name = "E3NN"
uuid = "1c50a8ea-cbe2-4d3e-83e0-d59f5e8851b3"
authors = [
"Deeptendu Santra <deeptendu.santra@protonmail.com> and contributors",
]
authors = ["Deeptendu Santra <deeptendu.santra@protonmail.com> and contributors"]
version = "0.1.0"

[deps]
BlockDiagonals = "0a1fb500-61f7-11e9-3c65-f5ef3456f9f0"
CoordinateTransformations = "150eb455-5306-5404-9cee-2592286d6298"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
MLUtils = "f1d291b0-491e-4a28-83b9-f70985020b54"
Expand All @@ -17,6 +16,7 @@ Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
TensorOperations = "6aa20fa7-93e2-5fca-9bc0-fbd0db3c71a2"

[compat]
BlockDiagonals = "0.2.0"
CoordinateTransformations = "0.6"
Quaternions = "0.7"
Rotations = "1"
Expand Down
1 change: 0 additions & 1 deletion docs/Project.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
[deps]
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
e3nn = "1c50a8ea-cbe2-4d3e-83e0-d59f5e8851b3"
10 changes: 6 additions & 4 deletions docs/make.jl
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
using Documenter, e3nn
using Documenter, E3NN

mathengine = MathJax3()
prettyurls = get(ENV, "CI", nothing) == "true"

makedocs(
modules = [e3nn],
modules = [E3NN],
doctest = false,
clean = true,
sitename = "e3nn.jl",
sitename = "E3NN.jl",
format = Documenter.HTML(;
mathengine,
prettyurls,
assets = ["assets/favicon.ico"],
collapselevel = 3
),
pages = ["Home" => "index.md", "API Reference" => ["o3" => "api/o3.md"]]
pages = ["Home" => "index.md", "Irreps" => "irreps.md",
"Examples" => "examples.md",
"API Reference" => ["Irreps" => "api/irreps.md"]]
)

deploydocs(repo = "github.com/Dsantra92/e3nn.jl.git")
7 changes: 7 additions & 0 deletions docs/src/api/irreps.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
## Irreducible Representation

```@autodocs
Modules = [E3NN.O3 ]
Pages = ["O3/irreps.jl"]
Private = false
```
6 changes: 3 additions & 3 deletions docs/src/api/o3.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
```@meta
CurrentModule = e3nn
CurrentModule = E3NN
```

```@autodocs
Modules = [o3]
Pages = ["o3/o3.jl", "o3/irreps.jl"]
Modules = [O3]
Pages = ["O3/O3.jl"]
Private = false
```
Binary file added docs/src/assets/irreps.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions docs/src/examples.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Examples
26 changes: 24 additions & 2 deletions docs/src/index.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,25 @@
# e3nn
# E3nn: E(3) Equivariant Neural Networks

Julia implementation of e3nn python library.
[E3nn.jl](https://github.com/Dsantra92/e3nn.jl) provides a pure julia implementation of the [e3nn framework](https://e3nn.org/).
It aims to provide fast and extendable APIs for working with $\mathbb{E}^3$ Equivariant Neural Networks and other performing related operations.
It is built on top of [GraphNeuralNetworks.jl]() and [Flux.jl]().
The APIs are generally consistent with e3nn's [PyTorch](https://github.com/e3nn/e3nn/) and [JAX](https://github.com/e3nn/e3nn-jax/) libraries but there might be certain differences.

## Installation

The package isn't available through the Julia Package Manager (yet).
If you want to use it, you can add it directly from GitHub.

```julia-repl
julia> using Pkg

julia> Pkg.add("https://github.com/Dsantra92/e3nn.jl.git")
```

!!! note
The package is still in under early stages of development and the APIs might change in the future.

## Getting started

We highly recommend starting with [Introduction to Irreps]() to gain some understanding of the primary components of the network.
If you are looking for a bit more hands on experience, have a look at the [examples]().
182 changes: 182 additions & 0 deletions docs/src/irreps.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
# Irreducible Representations of O(3)

A group representation $(D, V)$ describes the action of a group $G$ on a vector space $V$. Formally, this is written as:

```math
D: G \to \text{GL}(V)
```

where $\text{GL}(V)$ denotes the general linear group of $V$, i.e., the group of invertible linear transformations on $V$.

A representation of a group is a mapping(a literal matrix) from the group elements to the general linear group of matrices.
The irreducible representations, or _irreps_, are the "minimal" non-trivial representations of a group.
They are fundamental in the sense that any finite-dimensional representation of a group can be decomposed into a direct sum of irreps.

The orthogonal group $O(3)$ is the group of $3×3$ orthogonal matrices.
Geometrically, $O(3)$ represents all rotations and reflections in three-dimensional space that preserve distances and angles.
Any physical quantity, under the action of $O(3)$, transforms with a representation of $O(3)$

The special orthogonal group $SO(3)$ is a subgroup of $O(3)$. $SO(3)$ represents all rotations in three-dimensional space, excluding reflections.
$O(3)$ can be therefore be decomposed as a direct product of $SO(3)$ and the inversion group ${e, I}$:

$O(3) \cong SO(3) \times \{e, I\}$

where $e$ is the identity element of the group(here $3 \times 3$ identity matrix) and $I$ represents inversion(reflection) ($-1 \times$ identity matrix).

So, any element $g \in O(3)$ can be uniquely written as $g = ri$, where $r \in SO(3)$ and $i \in {e, I}$.

The irreps of $O(3)$ are the product of the irreps of $SO(3)$ and inversion.
The irreps of the $SO(3)$ group are called [Wigner matrices](https://en.wikipedia.org/wiki/Wigner_D-matrix) $D^L$.
The Inversion group has 2 irreps:

- The trivial representation $\sigma_+$, where inversion does nothing (multiplies by 1)
- The sign representation $\sigma_-$, where inversion flips the sign (multiplies by -1).

```math
\sigma_p(g) = \left \{ \begin{array}{l} 1 \text{ if } g = e \\ p \text{ if } g = I \end{array} \right..
```

Therefore, the irreps of an element $g \in O(3)$, where $g = ri$ is given by, $\sigma_p(i)D^L(r)$. In our library, we represent it using [`Irrep`](@ref).

And, [`Irreps`](@ref) represents the direct sum of irreps of $O(3)$:

```math
g = r i \mapsto \bigoplus_{j=1}^n m_j \sigma_{p_j}(i) D^{L_j}(r)
```

where $n \in \mathbb{N}$, $m_j \in \mathbb{N}$, $p_j \in \{+1, -1\}$, and $L_j \in \mathbb{N}_0$ for $j = 1, \ldots, n$.

![image](./assets/irreps.png)

## Irrep

The [`Irrep`](@ref) struct stores the degree $l$ and the parity $p$ of the representation $\sigma_p(i)D^l(r)$.

For a small recap:

- The variable $l$ represents the angular momentum quantum number or degree of the irrep.
- For $l$ = 0 , the representation is scalar, for $l$ = 1, the representation is a vector. For higher $l$, the representations are tensors of increasing rank, with dimension (2$l$ + 1).
- The parity $p$ indicates whether the irrep is invariant under reflection through the origin.
- A positive parity $( p = 1 )$ means the object behaves symmetrically under inversion, while negative parity $( p = -1 )$ implies antisymmetry, flipping sign upon inversion.
Together, $l$ and $p$ fully characterize how a function or field transforms under both rotation and inversion.

```jldoctest
julia> using E3NN.O3

julia> Irrep("1e")
1e

julia> Irrep(1, -1)
1o

```

Get the dimension of the representaion.

```jldoctest
julia> dim(Irrep("1e"))
3
```

## Irreps

The Irreps struct represents a direct sum of irreducible representations.
It is a collection of Irrep objects, each with an associated multiplicity.
This is the primary way to describe the structure of feature vectors in an equivariant neural network.

### Construction

You can create an Irreps object in several ways:From a string, which is the most common method:

```jldoctest
julia> Irreps("3x0e + 2x1o")
3x0e+2x1o
```

From a single Irrep, which will have a multiplicity of 1:

```jldoctest
julia> Irreps(Irrep("2e"))
1x2e
```

From a list (Vector or Tuple) of Irrep or MulIrrep objects:

```jldoctest
julia> Irreps([Irrep("0e"), Irrep("1o")])
1x0e+1x1o

julia> Irreps([(2, Irrep("1e")), (3, Irrep("2o"))])
2x1e+3x2o
```

An empty Irreps represents the zero-dimensional vector space.

```jldoctest
julia> Irreps()

julia> sprint(show, Irreps())
""
```

Properties and OperationsYou can inspect the properties of an Irreps object with several utility functions.The total dimension of the vector space is given by dim:

```jldoctest
julia> dim(Irreps("3x0e + 2x1o"))
9
```

The total number of irreps (sum of multiplicities) is given by num\*irreps:

```jldoctest
julia> num_irreps(Irreps("3x0e + 2x1o"))
5
```

The maximum `l` value is given by lmax:

```jldoctest
julia> lmax(Irreps("3x0e + 2x1o"))
1
```

You can perform a direct sum using the + operator. The result is automatically regrouped into a canonical form.

```jldoctest
julia> Irreps("1x1o") + Irreps("2x0e") + Irreps("1x1o")
2x0e+2x1o
```

You can scale the multiplicities using the \* operator.

```jldoctest
julia> 3 * Irreps("1x0e + 2x1o")
3x0e+6x1o
```

### Manipulation and Filtering

The library provides powerful functions to manipulate Irreps.
`regroup` sorts the irreps and combines identical ones by summing their multiplicities.
This is useful for creating a canonical representation.

```jldoctest
julia> regroup(Irreps("2x1o + 1x0e + 3x1o"))
1x0e+5x1o
```

`filter` allows you to select a subset of the irreps based on various criteria.

```jldoctest
julia> irreps = Irreps("3x0e + 2x1o + 4x2e")
3x0e+2x1o+4x2e

julia> filter(irreps, lmax=1)
3x0e+2x1o

julia> filter(irreps, keep=Irreps("0e + 2e"))
3x0e+4x2e

julia> filter(irreps, drop=mulir -> mulir.mul > 2)
2x1o
```
8 changes: 8 additions & 0 deletions src/E3NN.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module E3NN

# O3
include("O3/O3.jl")
using .O3
export Irrep

end
8 changes: 8 additions & 0 deletions src/O3/O3.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module O3

include("irreps.jl")
export Irrep, Irreps
export dim, isscalar, lmax, ls, count, mul_gcd, num_irreps,
remove_zero_multiplicities, simplify, sort, unify, regroup

end
Loading