Or if you have a direct description of the symmetry (i.e. orthogonal action and the basis for the linear space) you could try `SymbolicWedderburn.jl`

which will compute:

- the projections in the group ring (e.g. (
`1//2*() + 1//2*(1,2)`

and `1//2*() - 1//2*(1,2)`

)
- and realize them as orthogonal projections
**in the basis** using the representation.

In the sign action this will reduce to what @stevengj said, but it’s somehow automated if you’re willing to write a few functions. Here’s a direct example for the dihedral group acting on the linear space of polynomials in `x`

and `y`

of degree at most `4`

(it is taken/modified from the `examples/ex_robinson_form.jl`

);

```
julia> using SymbolicWedderburn, DynamicPolynomials, GroupsCore
julia> include("examples/action_polynomials.jl")
julia> include("examples/dihedral.jl")
julia> @polyvar x y
(x, y)
julia> struct DihedralAction <: OnMonomials end
julia> SymbolicWedderburn.coeff_type(::DihedralAction) = Float64
julia> function SymbolicWedderburn.action(
::DihedralAction,
el::DihedralElement,
mono::AbstractMonomial,
)
if iseven(el.reflection + el.id)
var_x, var_y = x, y
else
var_x, var_y = y, x
end
sign_x = 1 <= el.id <= 2 ? -1 : 1
sign_y = 2 <= el.id ? -1 : 1
return mono([x, y] => [sign_x * var_x, sign_y * var_y])
end
julia> G = DihedralGroup(4)
DihedralGroup(4)
julia> basis = monomials([x,y], 0:4)
15-element MonomialVector{true}:
x⁴
x³y
x²y²
xy³
y⁴
x³
x²y
xy²
y³
x²
xy
y²
x
y
1
julia> sa_basis = SymbolicWedderburn.symmetry_adapted_basis(Float64, G, DihedralAction(), basis, semisimple=true)
5-element Vector{SymbolicWedderburn.DirectSummand{Float64, SparseArrays.SparseMatrixCSC{Float64, Int64}}}:
[0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 1.0 0.0]
[0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 1.0; -0.7071067811865472 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0]
[0.0 -0.7071067811865472 … 0.0 0.0]
[0.0 0.0 … 0.0 0.0; 0.0 -0.7071067811865472 … 0.0 0.0]
[-0.7071067811865472 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0]
```

As can be seen, this action has `5`

isotypical components (defined by irreducible reps of the dihedral group) and `sa_basis`

defines pairwise orthogonal projections onto their isotypical subspaces (each projection has additionally orthogonal rows); These are the bases for the subspaces in a more human readable form:

```
julia> sa_basis[1]*basis # action via multiplication by -1
6-element Vector{Polynomial{true, Float64}}:
x³
x²y
xy²
y³
x
y
julia> sa_basis[2]*basis # trivial action = fixed subspaces
4-element Vector{Polynomial{true, Float64}}:
x²y²
1.0
-0.7071067811865472x⁴ - 0.7071067811865475y⁴
-0.7071067811865472x² - 0.7071067811865475y²
julia> sa_basis[3]*basis #
1-element Vector{Polynomial{true, Float64}}:
-0.7071067811865472x³y + 0.7071067811865475xy³
julia> sa_basis[4]*basis
2-element Vector{Polynomial{true, Float64}}:
xy
-0.7071067811865472x³y - 0.7071067811865475xy³
julia> sa_basis[5]*basis
2-element Vector{Polynomial{true, Float64}}:
-0.7071067811865472x⁴ + 0.7071067811865475y⁴
-0.7071067811865472x² + 0.7071067811865475y²
```

@Gregstrq I admit that for sign action that might be an overkill but hey, I can showcase my package . If you have more complicated symmetries (e.g. [signed] permutations) there’s much more reduction possible with minimal projection system etc.