AbelianEquationsSolver::AbelianEquationsSolver( const AbelianGroup& a , const VectorOf<Word>& v , int numOfVar ) : rawA( a ), A( FPGroup() ), rawSystem( v ), system( v.length() ), b( v.length() ), x( numOfVar ), torsion( numOfVar ), params( numOfVar ), numberOfVariables( numOfVar ), sysRank( 0 ), haveSol( -1 ) { FPGroup G( a.getFPGroup() ); VectorOf<Chars> q( G.numberOfGenerators() - numberOfVariables ); for( int i = numberOfVariables ; i < G.numberOfGenerators() ; i++ ) q[ i - numberOfVariables ] = (G.namesOfGenerators())[i]; if( G.getRelators().cardinality() ) { SetOf<Word> s = G.getRelators(); SetIterator<Word> I(s); SetOf<Word> news; while( !I.done() ) { Word w = I.value(); for( int j = 0 ; j < w.length() ; j++ ) { int p = Generator( w[j] ).hash(); if( p > 0 ) w[j] = Generator( p - numberOfVariables ); else w[j] = Generator( p + numberOfVariables ); } news.adjoinElement( w ); I.next(); } FPGroup G1( q , news ); A = AbelianGroup( G1 ); } else A = AbelianGroup( FPGroup(q) ); }
AbelianGroup MalcevSet::mapToQuotient(int k) const { if( ! isBasis ) error("MalcevSet::mapToQuotient: the set must be full"); // The generators of the quotient are basic commutators of weight k. const BasicCommutators& bc = theCollector.commutators(); int numGen = bc.numberOfWeight(k); int firstGen = bc.theFirstOfWeight(k) - 1; // The relators are Malcev basis words of weight k SetOf<Word> relsForAbelian; QuickAssociationsIterator< Generator, PolyWord > iter(theSet); for( ; ! iter.done(); iter.next() ) { // take a word from Malcev basis PolyWord pw = iter.value(); Letter first = pw.firstLetter(); if( ord(first.gen) != firstGen ) continue; //Ok, this is a word from the quotient. Abelianize it. ConstPolyWordIterator iter( pw ); Word w; for(iter.startFromLeft(); ! iter.done(); iter.stepRight() ) { Letter s = iter.thisLetter(); int newgen = ord(s.gen) - firstGen; if( newgen > numGen ) break; s.gen = Generator( newgen ); w *= Word(s); } relsForAbelian.adjoinElement(w); } // make the abelian quotient AbelianGroup abel( FPGroup(numGen, relsForAbelian) ); abel.computeCyclicDecomposition(); return abel; }
FPGroup FPGroup::triangulatePresentation( ) const { int new_gen_num = numOfGenerators; char str[10]; // rename old generators to avoid collisions vector< string > new_gen_names = initializeGenNames( numOfGenerators ); vector< Word > new_relators; int new_gens_num = 0; for( vector< Word >::const_iterator r_it=theRelators.begin( ) ; r_it!=theRelators.end( ) ; ++r_it ) { const Word& rel = *r_it; int len = rel.length( ); if( len>3 ) { // initial setup (first 3 letters) Word::const_iterator r_it = rel.begin( ); int g1 = *r_it++; int g2 = *r_it++; int g3 = *r_it++; strstream(str,10) << (++new_gens_num) << ends; new_gen_names.push_back( string( "x" ).append( str ) ); new_relators.push_back( Word( g1 )*Word( g2 )*Word( -new_gens_num ) ); // iterations for( int i=0 ; i<len-4 ; ++i, ++r_it ) { strstream(str,10) << (++new_gens_num) << ends; new_gen_names.push_back( string( "x" ).append( str ) ); int new_gen = new_gen_names.size( ); new_relators.push_back( Word( new_gens_num-1 ) * Word(g3) * Generator( -new_gens_num ) ); g3 = *r_it; } // the last relator new_relators.push_back( Word( g3 ) * Generator( *r_it ) * Word( -new_gens_num ) ); } else new_relators.push_back( rel ); } return FPGroup( FiniteAlphabet( new_gen_names) , new_relators ); }