Groups.jl/src/DirectProducts.jl

199 lines
6.0 KiB
Julia
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import Base: ×
export DirectProductGroup, DirectProductGroupElem
###############################################################################
#
# DirectProductGroup / DirectProductGroupElem
#
###############################################################################
doc"""
DirectProductGroup(factors::Vector{Group}) <: Group
Implements direct product of groups as vector factors. The group operation is
`*` distributed component-wise, with component-wise identity as neutral element.
"""
immutable DirectProductGroup{T<:Group} <: Group
factors::Vector{T}
end
immutable DirectProductGroupElem{T<:GroupElem} <: GroupElem
elts::Vector{T}
end
###############################################################################
#
# Type and parent object methods
#
###############################################################################
elem_type{T<:Group}(G::DirectProductGroup{T}) = DirectProductGroupElem{elem_type(first(G.factors))}
parent_type(::Type{DirectProductGroupElem}) = DirectProductGroup
parent(g::DirectProductGroupElem) = DirectProductGroup([parent(h) for h in g.elts])
###############################################################################
#
# DirectProductGroup / DirectProductGroupElem constructors
#
###############################################################################
end
DirectProductGroup{T<:Group}(G::T, H::T) = DirectProductGroup{T}([G, H])
×(G::Group, H::Group) = DirectProductGroup([G,H])
###############################################################################
#
# Parent object call overloads
#
###############################################################################
(G::DirectProductGroup)() = G([H() for H in G.factors])
(G::DirectProductGroup)(g::DirectProductGroupElem) = G(g.elts)
doc"""
(G::DirectProductGroup)(a::Vector; checked=true)
> Constructs element of the direct product group `G` by coercing each element
> of vector `a` to the corresponding factor of `G`. If `checked` flag is set to
> `false` no checks on the correctness are performed.
"""
function (G::DirectProductGroup){T<:GroupElem}(a::Vector{T})
length(a) == length(G.factors) || throw("Cannot coerce $a to $G: they have
different number of factors")
@assert elem_type(first(G.factors)) == T
return DirectProductGroupElem(a)
end
###############################################################################
#
# Basic manipulation
#
###############################################################################
function deepcopy_internal(g::DirectProductGroupElem, dict::ObjectIdDict)
G = parent(g)
return G(deepcopy(g.elts))
end
function hash(G::DirectProductGroup, h::UInt)
return hash(G.factors, hash(G.operations, hash(DirectProductGroup,h)))
end
function hash(g::DirectProductGroupElem, h::UInt)
return hash(g.elts, hash(g.parent, hash(DirectProductGroupElem, h)))
end
doc"""
eye(G::DirectProductGroup)
> Return the identity element for the given direct product of groups.
"""
eye(G::DirectProductGroup) = G()
###############################################################################
#
# String I/O
#
###############################################################################
function show(io::IO, G::DirectProductGroup)
println(io, "Direct product of groups")
join(io, G.factors, ", ", " and ")
end
function show(io::IO, g::DirectProductGroupElem)
print(io, "("*join(g.elts,",")*")")
end
###############################################################################
#
# Comparison
#
###############################################################################
function (==)(G::DirectProductGroup, H::DirectProductGroup)
G.factors == H.factors || return false
G.operations == H.operations || return false
return true
end
doc"""
==(g::DirectProductGroupElem, h::DirectProductGroupElem)
> Return `true` if the given elements of direct products are equal, otherwise return `false`.
"""
function (==)(g::DirectProductGroupElem, h::DirectProductGroupElem)
parent(g) == parent(h) || return false
g.elts == h.elts || return false
return true
end
###############################################################################
#
# Binary operators
#
###############################################################################
function direct_mult(g::DirectProductGroupElem, h::DirectProductGroupElem)
parent(g) == parent(h) || throw("Can't multiply elements from different groups: $g, $h")
G = parent(g)
return G([op(a,b) for (op,a,b) in zip(G.operations, g.elts, h.elts)])
end
doc"""
*(g::DirectProductGroupElem, h::DirectProductGroupElem)
> Return the direct-product group operation of elements, i.e. component-wise
> operation as defined by `operations` field of the parent object.
"""
(*)(g::DirectProductGroupElem, h::DirectProductGroupElem) = direct_mult(g,h)
###############################################################################
#
# Inversion
#
###############################################################################
doc"""
inv(g::DirectProductGroupElem)
> Return the inverse of the given element in the direct product group.
"""
# TODO: dirty hack around `+` operation
function inv(g::DirectProductGroupElem)
G = parent(g)
return G([(op == (*) ? inv(elt): -elt) for (op,elt) in zip(G.operations, g.elts)])
end
###############################################################################
#
# Misc
#
###############################################################################
doc"""
elements(G::DirectProductGroup)
> Returns `Task` that produces all elements of group `G` (provided that factors
> implement the elements function).
"""
# TODO: can Base.product handle generators?
# now it returns nothing's so we have to collect ellements...
function elements(G::DirectProductGroup)
cartesian_prod = Base.product([collect(elements(H)) for H in G.factors]...)
return (G(collect(elt)) for elt in cartesian_prod)
end
doc"""
order(G::DirectProductGroup)
> Returns the order (number of elements) in the group.
"""
order(G::DirectProductGroup) = prod([order(H) for H in G.factors])