# Revision history [back]

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\to H$, and $H\to F$. The composition $F\to H\to 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...)