2021-05-09 18:54:29 +02:00
function KnuthBendix . Alphabet ( S :: AbstractVector { <: GSymbol } )
S = unique! ( [ S ; inv . ( S ) ] )
inversions = [ findfirst ( == ( inv ( s ) ) , S ) for s in S ]
return Alphabet ( S , inversions )
end
2021-05-16 23:22:33 +02:00
struct AutomorphismGroup { G <: Group , T , R , S } <: AbstractFPGroup
2021-05-09 18:54:29 +02:00
group :: G
gens :: Vector { T }
rws :: R
domain :: S
end
object ( G :: AutomorphismGroup ) = G . group
rewriting ( G :: AutomorphismGroup ) = G . rws
2021-05-24 01:07:59 +02:00
function equality_data ( f :: FPGroupElement { <: AutomorphismGroup } )
imf = evaluate ( f )
# return normalform!.(imf)
tmp = one ( first ( imf ) )
for g in imf
normalform! ( tmp , g )
copyto! ( g , tmp )
end
return imf
end
2021-05-09 18:54:29 +02:00
2021-05-16 23:22:33 +02:00
function Base . : ( == ) ( g :: A , h :: A ) where { A <: FPGroupElement { <: AutomorphismGroup } }
2021-05-09 18:54:29 +02:00
@assert parent ( g ) === parent ( h )
if _isvalidhash ( g ) && _isvalidhash ( h )
hash ( g ) != hash ( h ) && return false
end
2021-05-16 22:30:50 +02:00
length ( word ( g ) ) > 8 && normalform! ( g )
length ( word ( h ) ) > 8 && normalform! ( h )
2021-05-09 18:54:29 +02:00
2021-05-16 22:30:50 +02:00
word ( g ) == word ( h ) && return true
2021-05-09 18:54:29 +02:00
img_computed , imh_computed = false , false
if ! _isvalidhash ( g )
2021-05-16 22:27:54 +02:00
img = equality_data ( g )
2021-05-09 18:54:29 +02:00
_update_savedhash! ( g , img )
img_computed = true
end
if ! _isvalidhash ( h )
2021-05-16 22:27:54 +02:00
imh = equality_data ( h )
2021-05-09 18:54:29 +02:00
_update_savedhash! ( h , imh )
imh_computed = true
end
@assert _isvalidhash ( g )
@assert _isvalidhash ( h )
hash ( g ) != hash ( h ) && return false
# words are different, but hashes agree
2021-05-16 23:16:35 +02:00
if ! img_computed
img = equality_data ( g )
end
if ! imh_computed
imh = equality_data ( h )
2021-05-09 18:54:29 +02:00
end
2021-05-16 22:27:54 +02:00
equal = img == imh
equal || @warn " hash collision in == : " g h
2021-05-09 18:54:29 +02:00
2021-05-16 22:27:54 +02:00
return equal
2021-05-09 18:54:29 +02:00
end
2021-05-26 12:03:28 +02:00
function Base . isone ( g :: FPGroupElement { <: AutomorphismGroup } )
if length ( word ( g ) ) > 8
normalform! ( g )
end
return evaluate ( g ) == parent ( g ) . domain
end
2021-05-09 18:54:29 +02:00
# eye-candy
2021-05-26 12:07:15 +02:00
Base . show ( io :: IO , :: Type { <: FPGroupElement { <: AutomorphismGroup { T } } } ) where { T } =
2021-05-16 23:22:33 +02:00
print ( io , " Automorphism{ $T ,…} " )
2021-05-09 18:54:29 +02:00
2021-05-26 12:07:15 +02:00
Base . show ( io :: IO , A :: AutomorphismGroup ) = print ( io , " automorphism group of " , object ( A ) )
2021-05-09 18:54:29 +02:00
## Automorphism Evaluation
domain ( f :: FPGroupElement { <: AutomorphismGroup } ) = deepcopy ( parent ( f ) . domain )
# tuple(gens(object(parent(f)))...)
2021-06-07 20:23:04 +02:00
evaluate ( f :: FPGroupElement { <: AutomorphismGroup } ) = evaluate! ( domain ( f ) , f )
function evaluate! (
t :: NTuple { N , T } ,
f :: FPGroupElement { <: AutomorphismGroup { <: Group } } ,
tmp = one ( first ( t ) ) ,
) where { N , T }
A = alphabet ( f )
AF = alphabet ( object ( parent ( f ) ) )
for idx in word ( f )
t = @inbounds evaluate! ( t , A [ idx ] , AF , tmp ) :: NTuple { N , T }
end
return t
2021-05-09 18:54:29 +02:00
end
2021-06-07 20:23:04 +02:00
evaluate! ( t :: NTuple { N , T } , s :: GSymbol , A , tmp = one ( first ( t ) ) ) where { N , T } = throw ( " you need to implement `evaluate!(:: $ ( typeof ( t ) ) , :: $ ( typeof ( s ) ) , ::Alphabet, tmp=one(first(t)))` " )