![]() | 1 | initial version |
The type of solution i had in mind, while typing the comment, was of the following shape:
F.<a,b,c> = FreeGroup()
H.<s,t,u> = FreeGroup()
h2f_DIC = { 1: a*b , # s "is" a*b :: map s -> a*b
2: b , # t "is" b :: map t -> b
3: b*c , # u "is" b*c :: map u -> b*c
}
f2h_DIC = { 1: s*t^(-1),
2: t ,
3: t^(-1)*u, }
for dic in h2f_DIC, f2h_DIC:
for key, val in dic.items():
dic[-key] = val^(-1)
def h2f( d ):
"""d is an element of F.<a,b,c>, map it to H by using f2h_DIC
"""
return prod( [ f2h_DIC[j] for j in d.Tietze() ] )
def f2h( w ):
"""w is an element of H.<s,t,u>, map it to F by using h2f_DIC
"""
return prod( [ h2f_DIC[j] for j in w.Tietze() ] )
d = a * b * a * b^-1 * c * a^2 * c^3 * b * c^-3
print "d = %s" % d
print "d.Tietze() = %s" % str( d.Tietze() )
w = h2f( d )
print "w = %s" % w
print "w.Tietze() = %s" % str( w.Tietze() )
print "f2h( h2f( d ) ) == d is %s" % bool( f2h( h2f( d ) ) == d )
which delivers:
d = a*b*a*b^-1*c*a^2*c^3*b*c^-3
d.Tietze() = (1, 2, 1, -2, 3, 1, 1, 3, 3, 3, 2, -3, -3, -3)
w = s^2*t^-3*u*(s*t^-1)^2*(t^-1*u)^3*(t*u^-1)^3*t
w.Tietze() = (1, 1, -2, -2, -2, 3, 1, -2, 1, -2, -2, 3, -2, 3, -2, 3, 2, -3, 2, -3, 2, -3, 2)
f2h( h2f( d ) ) == d is True
However not in this ugly, unstructural way do define morphisms by hand, well, i hoped for us, that something like F.hom( ... )
would work. No chance... The above is the best i can deliver in time...
Anyway, the above is the best structural solution i could see, that works without too much pain in both directions, F→H, and H→F. The composition F→H→F was tested above to be the identity, at least when applied on some random element d.
(We really need the usual structural morphisms. As seen above, there should be not so complicated to implement them somehow, even also not optimal for a first approach...)