#include "algorithms/decompose.hh" #include "algorithms/collect_terms.hh" #include "algorithms/rename_dummies.hh" #include "algorithms/young_project_product.hh" #include "properties/TableauBase.hh" #include "Linear.hh" using namespace cadabra; decompose::decompose(const Kernel& k, Ex& tr, Ex& b) : Algorithm(k, tr), basis(b) { } bool decompose::can_apply(iterator it) { if(*it->name!="\\prod") return false; return true; } void decompose::add_element_to_basis(Ex& projterm, Ex::iterator projtermit) { // Add a new column for the new term in the basis for(unsigned int ii=0; iiname=="\\sum") { sibling_iterator moreit=projterm.begin(projtermit); while(moreit!=projterm.end(projtermit)) { multiplier_t remember_mult=*moreit->multiplier; one(moreit->multiplier); bool thistermfound=false; for(unsigned int ypi=0; ypi crow(coefficient_matrix.size()>0? coefficient_matrix[0].size():1,0); crow.back()=remember_mult; coefficient_matrix.push_back(crow); // txtout << "added new monomial" << std::endl; } ++moreit; } } else { multiplier_t remember_mult=*projtermit->multiplier; one(projtermit->multiplier); bool thistermfound=false; for(unsigned int ypi=0; ypi crow(coefficient_matrix.size()>0? coefficient_matrix[0].size():1,0); crow.back()=remember_mult; coefficient_matrix.push_back(crow); } } } Algorithm::result_t decompose::apply(iterator& it) { bool ypproject=true; #ifdef DEBUG std::cerr << "Projecting on basis " << basis.begin() << std::endl; #endif iterator basisit=basis.begin(); if(! (*basisit->name=="\\comma")) { sibling_iterator fr=basis.begin(); sibling_iterator nd=fr; ++nd; // basis should be a list; write it as such even if there's only one element. basisit->fl.bracket=str_node::b_none; basisit=tr.wrap(basisit, str_node("\\comma")); } Ex projbasis; projbasis.set_head(str_node("\\expression")); terms_from_yp.clear(); coefficient_matrix.clear(); // Some overlap with code in all_contractions. bool nontrivial_symmetries_present=false; sibling_iterator factorit=tr.begin(it); while(factorit!=tr.end(it)) { // Do this always, even if ypproject==false, since we need it for rhs. if(tr.number_of_children(factorit)>1) { const TableauBase *tb = kernel.properties.get(factorit); if(tb) if(!tb->is_simple_symmetry(kernel.properties, tr, it)) { nontrivial_symmetries_present=true; break; } } ++factorit; } // Setup the coefficient matrix. if(nontrivial_symmetries_present && ypproject) { //debugout << "Going to project the basis." << std::endl; // Need to make a Young-projected basis. sibling_iterator sib=tr.begin(basisit); while(sib!=tr.end(basisit)) { // debugout << "Next term in the basis." << std::endl; Ex projterm; projterm.set_head(str_node("\\expression")); projterm.append_child(projterm.begin(), (iterator)(sib)); #ifdef OLDVERSION young_project_tensor ypt(projterm, projterm.end()); ypt.modulo_monoterm=true; iterator projtermit=projterm.begin(projterm.begin()); ypt.apply_generic(projtermit, true, false, 0); distribute dbt(kernel, projterm); canonicalise can(kernel, projterm); // can.method=canonicalise::xperm; rename_dummies ren(kernel, projterm); collect_terms ct(kernel, projterm); dbt.apply_generic(projtermit, false);// FIXME: URGENT: should check consistency ren.apply_recursive(projtermit, false); // by far the slowest step if(*projtermit->name=="\\sum") ct.apply(projtermit); can.apply_recursive(projtermit, false); ren.apply_recursive(projtermit, false); if(*projtermit->name=="\\sum") ct.apply(projtermit); #else iterator projtermit=projterm.begin(projterm.begin()); young_project_product ypp(kernel, projterm); // sumflatten sf(kernel, projterm); collect_terms ct(kernel, projterm); rename_dummies ren(kernel, projterm, "", ""); ypp.apply_generic(projtermit, true, false, 0); // sf.apply_recursive(projtermit, false); ren.apply_generic(projtermit, true, false, 0); // by far the slowest step if(*projtermit->name=="\\sum") ct.apply(projtermit); sibling_iterator sib2=tr.begin(projtermit); while(sib2!=tr.end(projtermit)) { sib2->fl.bracket=str_node::b_none; ++sib2; } #endif // After young projection, we may get identically zero. if(projtermit->is_zero()) { // txtout << "An element of the basis is identically zero after Young projection." << std::endl; return result_t::l_error; } add_element_to_basis(projterm, projtermit); ++sib; } // debugout << "Young-projected basis constructed." << std::endl; } else { // Copy the basis straight into the terms_from_yp. assert(*basisit->name=="\\comma"); sibling_iterator sib=tr.begin(basisit); while(sib!=tr.end(basisit)) { Ex projterm(sib); iterator projtermit=projterm.begin(); sibling_iterator sib2=tr.begin(projtermit); while(sib2!=tr.end(projtermit)) { sib2->fl.bracket=str_node::b_none; ++sib2; } add_element_to_basis(projterm, projtermit); ++sib; } // debugout << "Kept old young-projected basis." << std::endl; } // Young project the rhs. Ex rhstree; rhstree.set_head(str_node("\\expression")); rhstree.append_child(rhstree.begin(), it); iterator rhsit=rhstree.begin(rhstree.begin()); if(nontrivial_symmetries_present) { #ifdef OLDVERSION young_project_tensor ypt(rhstree, rhstree.end()); ypt.modulo_monoterm=true; ypt.apply_generic(rhsit, true, false, 0); if(*rhsit->name=="\\prod") { distribute dbt(rhstree, rhstree.end()); canonicalise can(rhstree, rhstree.end()); rename_dummies ren(rhstree, rhstree.end()); collect_terms ct(rhstree, rhstree.end()); dbt.apply(rhsit); ren.apply_generic(rhsit, true, false, 0); if(*rhsit->name=="\\sum") ct.apply(rhsit); can.apply_generic(rhsit, true, false, 0); ren.apply_generic(rhsit, true, false, 0); if(*rhsit->name=="\\sum") ct.apply(rhsit); } #else young_project_product ypp(kernel, rhstree); // sumflatten sf(rhstree, rhstree.end()); collect_terms ct(kernel, rhstree); rename_dummies ren(kernel, rhstree, "", ""); // debugout << "young project rhs." << std::endl; ypp.apply_generic(rhsit, true, false, 0); // debugout << "sumflatten." << std::endl; // sf.apply_recursive(rhsit, false); // debugout << "rename." << std::endl; ren.apply_generic(rhsit, true, false, 0); // by far the slowest step // debugout << "collect terms." << std::endl; ct.apply_generic(rhsit, true, false, 0); // debugout << "rhs projection done." << std::endl; sibling_iterator sib2=rhstree.begin(rhsit); while(sib2!=rhstree.end(rhsit)) { sib2->fl.bracket=str_node::b_none; ++sib2; } #endif } // debugout << "Young-projected rhs constructed" << std::endl; // rhstree.print_recursive_treeform(debugout, rhstree.begin()); std::vector rhs(terms_from_yp.size(),0); if(*rhsit->name=="\\sum") { // iterate over all terms sibling_iterator rhssumit=rhstree.begin(rhsit); while(rhssumit!=rhstree.end(rhsit)) { bool found_in_basis=false; multiplier_t rhsmult=*rhssumit->multiplier; one(rhssumit->multiplier); for(unsigned int i=0; iis_zero()==false) { bool found_in_basis=false; multiplier_t rhsmult=*rhsit->multiplier; one(rhsit->multiplier); for(unsigned int i=0; iis_zero()) { // debugout << "rhs is identically zero" << std::endl; Ex res; res.set_head(str_node("\\comma")); for(unsigned int i=0; imultiplier=rat_set.insert(0).first; tr.replace(it, res.begin()); } else { // debugout << "doing gaussian elimination" << std::endl; if(linear::gaussian_elimination_inplace(coefficient_matrix, rhs)) { // for(unsigned int i=0; imultiplier=rat_set.insert(rhs[i]).first; it=tr.replace(it, res.begin()); } else { // txtout << "decomposing impossible" << std::endl; // tr.print_recursive_treeform(txtout, it); return result_t::l_error; } } return result_t::l_applied; }