Add graphs from group actions graph_from_group_action([::Type{T},] G, L, act, adj) where {T <: Union{Directed, Undirected}} and graph_from_group_action([::Type{T},] Omega::GSet, adj) where {T <: Union{Directed, Undirected}} - #6159
Conversation
…, L, act, adj) where {T <: Union{Directed, Undirected}}` and `graph_from_group_action([::Type{T},] Omega::GSet, adj) where {T <: Union{Directed, Undirected}}`
|
@mjrodgers and @ThomasBreuer will have a (quick) look at this. |
|
Hi thanks for contributing this! I notice that this is sort of done without using a lot of the functionality we have already. For example, you seem to convert the group action to permutations on function orbits_on_pairs(Omega::GSet)
acthom = action_homomorphism(Omega)
H = image(acthom)
d = degree(H)
OmegaPairs = gset(H, [[i,j] for i in 1:d, j in 1:d])
return orbits(OmegaPairs)
endthis avoids any complications from exotic action functions. And then it is easy to decide which orbits get used as edges in the graph. Can you use this to make your code simpler? Is the performance still acceptable using this (and would it still do everything you want)? (I guess you would want to eliminate the pairs |
Thanks for the review. We carefully evaluated the orbital (pair-orbit) approach and benchmarked it against the current implementation. The two are mathematically equivalent and produce identical edge sets, but we propose keeping the current implementation, because the design goal is to scale to larger graphs, which conflicts with the O(d²) bound of the orbital approach.
We therefore suggest keeping the current implementation. If pair-orbits are useful as a standalone feature, we can add |
|
Briefly touched upon this in triage. @mjrodgers has some more comments which will probably follow, soon. @ThomasBreuer and him are still looking into this. |
|
@long-zm123 Concerning your comment
Could you please show an example where this problem occurs? I have no idea how to construct such a situation. |
|
Hi @ThomasBreuer, thanks for the question — here is a concrete, reproducible example. Minimal example. Let G = S₄, H = Stab(1) ≅ S₃, and let G act on the left cosets of H by left multiplication, written as a Julia function: using Oscar
G = symmetric_group(4)
H, _ = stabilizer(G, 1) # H = Stab(1), |H| = 6
c = left_coset(H, G([2, 1, 3, 4])) # the left coset (1,2)·H
act = (x, g) -> g * x # left multiplication, a Julia function
st, _ = stabilizer(G, c, act) # goes to GAP's Stabilizer
println("order of returned stabilizer: ", order(st))
for h in gens(st)
println(h, " fixes c? ", act(c, h) == c)
endOutput (Oscar 1.9.0-DEV, GAP 4.16): The true stabilizer of c = (1,2)·H is (1,2)·H·(1,2)⁻¹, which has order 6. GAP's Why this happens. GAP's group-action machinery assumes a right action, This is not a rare corner case. For G = S₆, H = Stab({1,2}) (|H| = 48) acting by left multiplication on its 15 left cosets, GAP's Why the guard in the PR is there. The implementation does not blindly trust the GAP result: for every returned generator (For completeness: the alternative |
|
@long-zm123 Left multiplication |
Return the graph on the vertices
1:length(L)with a directed edge(i, j)if and only if
adj(L[i], L[j])returnstrue.The group
Gmust act on the listLvia the action functionact, i.e.act(x, g)is the image ofx in Lunderg in G, andLmust be invariantunder this action. The elements of
Lmust be pairwise distinct. Theadjacency predicate
adjmust be invariant under the action ofG, i.e.adj(x, y) == adj(act(x, g), act(y, g))holds for allx, y in Land allg in G.If a G-set
Omegais passed instead ofG,L,act, then the group, thevertex list and the action function are taken from
Omega; the call isequivalent to
graph_from_group_action(T, acting_group(Omega), collect(Omega), action_function(Omega), adj). The vertices of the resulting graph are theelements of
collect(Omega)in their given order.If the first argument is omitted, or is
Directed, then the returned graph isdirected; if it is
Undirected, then the returned graph is undirected and itsedges are obtained by symmetrizing the directed ones.
Examples