QList<int> FnWord::abelianization(const Basis &basis) const { // returns an integer list of basis elements exponent sums int rank = basis.getRank(); QList<int> abelian_image; for(int i = 0; i < rank; i++) abelian_image.append(count(basis.at(2*i)) - count(basis.at(2*i+1))); return abelian_image; }
QList<int> FnWord::stepTwoNilpotentNormalForm(const Basis & basis) const { // returns an integer list of the two step nilpotent normal form of the element int rank = basis.getRank(); QList<int> nilpotent_image = abelianization(basis); QList<int> commutator_portion; int index = 0; for(int i = 0; i < rank; i++) { for(int j = i+1; j < rank; j++) { QString ijBasis(basis); ijBasis.remove(2*j,2); ijBasis.remove(2*i,2); FnWord ijWord(*this); ijWord.remove(QRegExp("["+ijBasis+"]")); ijWord.tighten(); // integrate -y dx int integral = 0; commutator_portion.append(0); for(int k = 0; k < ijWord.length(); k++) { if(ijWord.at(k) == basis.at(2*i)) commutator_portion[index] += integral; if(ijWord.at(k) == basis.at(2*i + 1)) commutator_portion[index] -= integral; if(ijWord.at(k) == basis.at(2*j)) integral -= 1; if(ijWord.at(k) == basis.at(2*j + 1)) integral += 1; } index++; } } nilpotent_image.append(commutator_portion); return nilpotent_image; }
FnGraph FnWord::whiteheadGraph(const Basis &basis) const { FnGraph whitehead; QString edge; int i; for(i = 0; i < 2*basis.getRank(); i++) whitehead.addVertex(basis.at(i)); for(i = 0; i < length()-1; i++) whitehead.addEdge(edge.setNum(i),at(i),basis.inverse(at(i+1))); whitehead.addEdge(edge.setNum(i),at(i),basis.inverse(at(0))); return whitehead; }
FnMap whiteheadProblem(const FnWord &u, const FnWord &v, const Basis &basis) { /* Determines if there is an automorphism phi such that u = phi(v). If yes, the map is returned. Else, the Fail map is returned. */ int i,r = basis.getRank(); int min_len; FnWord tmp,v_tmp; FnWord u_min,v_min; FnMap phi(r); FnMap whAuto(r); FnMap rho(r),sigma(r),tau(r); FnMap phi_u(r),phi_v(r),phi_u_inv(r); // get minimal length representatives phi_u = minimizeLength(u,basis); phi_v = minimizeLength(v,basis); u_min = phi_u(u); v_min = phi_v(v); // easy case, minimum lengths are different if (u_min.length() != v_min.length()) { phi.fail(); return phi; } min_len = u_min.length(); phi_u_inv = phi_u.isAutomorphism(); // other easy case, u_min = v_min if (u_min == v_min) { // u = phi_u^-1 (phi_v(v)) phi = phi_u_inv*phi_v; return phi; } // now the hard case... need to find all words of length u_min related // by Whitehead moves and permutations... // build Whitehead data QList<WhiteheadData> whAutos = whiteheadAutos(basis); QListIterator<WhiteheadData> move(whAutos); // define the permutation automorphisms for (i = 0; i < r-1; i++) { // i -> i+1 rho.insert(basis.at(2*i),FnWord(basis.at(2*i + 2))); rho.insert(basis.at(2*i + 1),FnWord(basis.at(2*i + 3))); } rho.insert(basis.at(2*r - 2),FnWord(basis.at(0))); rho.insert(basis.at(2*r - 1),FnWord(basis.at(1))); sigma.insert(basis.at(0),FnWord(basis.at(1))); // a -> A sigma.insert(basis.at(1),FnWord(basis.at(0))); // A -> a tau.insert(basis.at(0),FnWord(basis.at(2))); // a -> b tau.insert(basis.at(1),FnWord(basis.at(3))); // A -> B tau.insert(basis.at(2),FnWord(basis.at(0))); // b -> a tau.insert(basis.at(3),FnWord(basis.at(1))); // B -> A int n = 0; QList<FnWord> v_rel; QHash<FnWord, FnMap> wh_v; // wh_v[x](v_min) = x v_rel.append(v_min); wh_v.insert(v_min,FnMap(r)); // looped over words with the same length as v while (n < v_rel.size()) { v_tmp = v_rel.at(n++); move.toFront(); // loop over Whitehead moves while (move.hasNext()) { whAuto = whitehead(move.next(),basis); tmp = whAuto(v_tmp); if (tmp.length() == min_len) { if (!v_rel.contains(tmp)) { v_rel.append(tmp); wh_v.insert(tmp,whAuto*wh_v.value(v_tmp)); } if (tmp == u_min) { // found it! phi_v = wh_v.value(tmp)*phi_v; // phi_u(u) = tmp = phi_v(v) phi = phi_u_inv*phi_v; // u = phi_u^-1 phi_v(v) return phi; } } } // end while (move.hasNext()) // loop over permutation moves, these don't change length tmp = rho(v_tmp); if (!v_rel.contains(tmp)) { v_rel.append(tmp); wh_v.insert(tmp,rho*wh_v.value(v_tmp)); } if (tmp == u_min) { // found it! phi_v = wh_v.value(tmp)*phi_v; // phi_u(u) = tmp = phi_v(v) phi = phi_u_inv*phi_v; // u = phi_u^-1 phi_v(v) return phi; } tmp = sigma(v_tmp); if (!v_rel.contains(tmp)) { v_rel.append(tmp); wh_v.insert(tmp,sigma*wh_v.value(v_tmp)); } if (tmp == u_min) { // found it! phi_v = wh_v.value(tmp)*phi_v; // phi_u(u) = tmp = phi_v(v) phi = phi_u_inv*phi_v; // u = phi_u^-1 phi_v(v) return phi; } tmp = tau(v_tmp); if (!v_rel.contains(tmp)) { v_rel.append(tmp); wh_v.insert(tmp,tau*wh_v.value(v_tmp)); } if (tmp == u_min) { // found it! phi_v = wh_v.value(tmp)*phi_v; // phi_u(u) = tmp = phi_v(v) phi = phi_u_inv*phi_v; // u = phi_u^-1 phi_v(v) return phi; } } // end while (x.hasNext()) // didn't find it phi.fail(); return phi; }