// COPYRIGHT 2020 Claudius Zibrowius // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . #ifndef BNALGEBRA_TPP #define BNALGEBRA_TPP #ifndef BNALGEBRA_H #include "BNAlgebra.h" #endif // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // BNObj // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% BNObj::BNObj(bool idem,int h, int q) : idem(idem), h(h), q(q) { } // // // output and sanity checks // // // void BNObj::print() const { std::cout << this->to_string() <<"\n"; } std::string BNObj::to_string(bool with_grading) const{ std::string output; if (idem){output+="●";} else {output+="○";}; if (with_grading){ output+= (" h^"+std::to_string(h)); output+= (" q^"+std::to_string(q)); output+= (" δ^"+std::to_string(this->get_delta2()/2)); }; return output; } std::string BNObj::to_TeX() const{ std::string output; if (idem){output+="\\DotB";} else {output+="\\DotC";}; output+= ("h^{"+std::to_string(h)+"}"); output+= ("q^{"+std::to_string(q)+"}"); output+= ("\\delta^{"+std::to_string(this->get_delta2()/2)+"}"); return output; } // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // Label // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% template Label::Label(int type, Coeff coeff) : type(type), coeff(coeff){ }; // // // output // // // template std::string Label::to_string(bool with_coeff) const { std::string output; if (with_coeff){ output+=coeff_to_string(coeff); output+="."; }; if (type>0){ output+=("D^"+std::to_string(type)); } else if (type==0){ output+=("id"); } else{ output+=("S^"+std::to_string(-type)); }; return output; }; // // // main methods // // // template bool label_is_zero(const Label &label){ // this function is used in BNMor::simplify(). return coeff_is_0(label.coeff); } // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // BNMor // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% template BNMor::BNMor(int i) : front(BNObj()), back(BNObj()), labels({}){ } template BNMor::BNMor() : front(BNObj()), back(BNObj()), labels({}){ } template BNMor::BNMor(BNObj front, BNObj back, std::list> labels) : front(front), back(back), labels(labels) { } // // // output and sanity checks // // // template std::string BNMor::to_string(bool with_coeff) const { std::string s; if (labels.empty()){ return "0"; } else { for (auto label: labels){ s+=label.to_string(with_coeff); s+="+"; }; s.resize(s.size()-1); }; return s; } template void BNMor::print() const { if (labels.empty()) { std::cout << "The zero-morphism.\n"; } else { std::cout << front.to_string() << "---("; std::cout << this->to_string(); std::cout << ")--->" << back.to_string(); }; } template bool BNMor::check(const BNObj &obj_from, const BNObj &obj_to) const{ if (labels.empty()){return true;}; // We may now assume that the morphism is non-zero. if (front!=obj_from){return false;}; if (back!=obj_to){return false;}; return true; }; // // // main methods // // // template bool BNMor::is_id() const{ // we assume that the morphism is simplified if (labels.size()!=1){return false;}; if (labels.front().type!=0){return false;}; if (is_inv(labels.front().coeff)!=true){return false;}; return true; }; template BNMor BNMor::simplify() { if(labels.empty()){return BNMor(0);}; // We may now assume that the list of labels is non-empty. // 1) order labels using the overloaded operation< on labels labels.sort(); // 2) for each label, except the first, check if it is equal to the // predecessor except for the coefficient. std::list> new_labels={labels.front()}; labels.erase(labels.begin()); for (const Label &label : labels) { if (label==new_labels.back()){ new_labels.back().coeff+=label.coeff; } else{ new_labels.push_back(label); }; }; // 3) eliminate labels that are zero. new_labels.remove_if(label_is_zero); labels=new_labels; return *this; } template<> template BNMor BNMor::to_coeffs() const { std::list> new_labels; for (auto label : labels){ New_Coeff new_coeff=label.coeff; if (coeff_is_0(new_coeff)!=true){ new_labels.push_back(Label(label.type,new_coeff)); }; }; return BNMor(front,back,new_labels); }; // // // overloaded operators // // // template bool BNMor::operator== (const BNMor &mor2) const { if ((labels.empty())&&(mor2.labels.empty())){return true;}; if (front!=mor2.front){return false;}; if (back!=mor2.back){return false;}; if (labels.size()!=mor2.labels.size()){return false;}; std::list> temp=mor2.labels; for (auto label : labels){ // testing if the two lists of labels are equal as sets. We assume // that 'mor1' and 'mor2' are fully simplified. auto iter=std::find(temp.begin(),temp.end(),label); if (iter==temp.end()){return false;} else{ temp.erase(iter); }; }; return true; } template void BNMor::operator*= (const Coeff &scalar){ for (auto &label : labels){ label.coeff*=scalar; }; } template BNMor BNMor::operator- () const { // multiply the morphism by -1; std::list> new_labels=labels; for (Label &label : new_labels){ label.coeff=-1*label.coeff; }; return BNMor(front,back,new_labels); } template BNMor BNMor::operator*(const Coeff &scalar) const { auto new_mor=*this; for (auto &label : new_mor.labels){ label.coeff*=scalar; }; return new_mor; }; template BNMor BNMor::operator*(const BNMor &mor1) const { if (mor1.labels.empty() || labels.empty()){ return BNMor(0); }; //multiplication with the zero-morphism. if(front!=mor1.back){ // Not necessary, if we trust the program. std::cout << "WARNING: You are trying to compose two incomposable morphisms.\n"; }; //morphisms compose as BNMor(b,c)*BNMor(a,b)=BNMor(a,c) std::list> new_labels={}; for (const Label &label1 : mor1.labels){ for (const Label &label2 : labels){ // now multiply each pair of labels if (label1.type*label2.type>=0){ new_labels.push_back(Label(label1.type+label2.type,label1.coeff*label2.coeff)); }; }; }; return BNMor(mor1.front,back,new_labels).simplify(); } template BNMor BNMor::operator+ (const BNMor &mor2) const { if (labels.empty()){ BNMor output=mor2; //making copy return output; }; if (mor2.labels.empty()){ BNMor output=*this; //making copy return output; }; std::list> new_labels=labels; new_labels.insert(new_labels.end(), mor2.labels.begin(), mor2.labels.end()); // concatenate labels1 and labels2 return BNMor(front, back, new_labels).simplify(); } #endif