/** @file color.cpp * * Implementation of GiNaC's color objects. * No real implementation yet, to be done. */ /* * GiNaC Copyright (C) 1999-2000 Johannes Gutenberg University Mainz, Germany * * 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 2 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, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include "color.h" #include "ex.h" #include "coloridx.h" #include "ncmul.h" #include "numeric.h" #include "relational.h" #include "archive.h" #include "debugmsg.h" #include "utils.h" #ifndef NO_NAMESPACE_GINAC namespace GiNaC { #endif // ndef NO_NAMESPACE_GINAC GINAC_IMPLEMENT_REGISTERED_CLASS(color, indexed) ////////// // default constructor, destructor, copy constructor assignment operator and helpers ////////// // public color::color() : type(invalid), representation_label(0) { debugmsg("color default constructor",LOGLEVEL_CONSTRUCT); tinfo_key=TINFO_color; } color::~color() { debugmsg("color destructor",LOGLEVEL_DESTRUCT); destroy(0); } color::color(const color & other) { debugmsg("color copy constructor",LOGLEVEL_CONSTRUCT); copy (other); } const color & color::operator=(const color & other) { debugmsg("color operator=",LOGLEVEL_ASSIGNMENT); if (this != &other) { destroy(1); copy(other); } return *this; } // protected void color::copy(const color & other) { inherited::copy(other); type=other.type; representation_label=other.representation_label; } void color::destroy(bool call_parent) { if (call_parent) { inherited::destroy(call_parent); } } ////////// // other constructors ////////// // protected color::color(color_types const t, unsigned rl) : type(t), representation_label(rl) { debugmsg("color constructor from color_types,unsigned",LOGLEVEL_CONSTRUCT); GINAC_ASSERT(representation_labelsetflag(status_flags::dynallocated); } /** Archive the object. */ void color::archive(archive_node &n) const { inherited::archive(n); n.add_unsigned("type", type); n.add_unsigned("representation", representation_label); } ////////// // functions overriding virtual functions from bases classes ////////// // public basic * color::duplicate() const { debugmsg("color duplicate",LOGLEVEL_DUPLICATE); return new color(*this); } void color::printraw(ostream & os) const { debugmsg("color printraw",LOGLEVEL_PRINT); os << "color(type=" << (unsigned)type << ",representation_label=" << representation_label << ",indices="; printrawindices(os); os << ",hash=" << hashvalue << ",flags=" << flags << ")"; } void color::printtree(ostream & os, unsigned indent) const { debugmsg("color printtree",LOGLEVEL_PRINT); os << string(indent,' ') << "color object: " << "type=" << (unsigned)type << ",representation_label=" << representation_label << ", "; os << seq.size() << " indices" << endl; printtreeindices(os,indent); os << string(indent,' ') << "hash=" << hashvalue << " (0x" << hex << hashvalue << dec << ")" << ", flags=" << flags << endl; } void color::print(ostream & os, unsigned upper_precedence) const { debugmsg("color print",LOGLEVEL_PRINT); switch (type) { case color_T: os << "T"; if (representation_label!=0) { os << "^(" << representation_label << ")"; } break; case color_f: os << "f"; break; case color_d: os << "d"; break; case color_delta8: os << "delta8"; break; case color_ONE: os << "color_ONE"; break; case invalid: default: os << "INVALID_COLOR_OBJECT"; break; } printindices(os); } void color::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const { debugmsg("color print csrc",LOGLEVEL_PRINT); print(os,upper_precedence); } bool color::info(unsigned inf) const { return inherited::info(inf); } #define CMPINDICES(A,B,C) ((idx1.get_value()==(A))&&(idx2.get_value()==(B))&&(idx3.get_value()==(C))) ex color::eval(int level) const { // canonicalize indices bool antisymmetric=false; switch (type) { case color_f: antisymmetric=true; // no break here! case color_d: case color_delta8: { exvector iv=seq; int sig=canonicalize_indices(iv,antisymmetric); if (sig!=INT_MAX) { // something has changed while sorting indices, more evaluations later if (sig==0) return _ex0(); return ex(sig)*color(type,iv,representation_label); } } break; default: // nothing to canonicalize break; } switch (type) { case color_delta8: { GINAC_ASSERT(seq.size()==2); const coloridx & idx1=ex_to_coloridx(seq[0]); const coloridx & idx2=ex_to_coloridx(seq[1]); // check for delta8_{a,a} where a is a symbolic index, replace by 8 if ((idx1.is_symbolic())&&(idx1.is_equal_same_type(idx2))) { return ex(COLOR_EIGHT); } // check for delta8_{a,b} where a and b are numeric indices, replace by 0 or 1 if ((!idx1.is_symbolic())&&(!idx2.is_symbolic())) { if ((idx1.get_value()!=idx2.get_value())) { return _ex1(); } else { return _ex0(); } } } break; case color_d: // check for d_{a,a,c} (=0) when a is symbolic { GINAC_ASSERT(seq.size()==3); const coloridx & idx1=ex_to_coloridx(seq[0]); const coloridx & idx2=ex_to_coloridx(seq[1]); const coloridx & idx3=ex_to_coloridx(seq[2]); if (idx1.is_equal_same_type(idx2) && idx1.is_symbolic()) { return _ex0(); } else if (idx2.is_equal_same_type(idx3) && idx2.is_symbolic()) { return _ex0(); } // check for three numeric indices if (!(idx1.is_symbolic()||idx2.is_symbolic()||idx3.is_symbolic())) { GINAC_ASSERT(idx1.get_value()<=idx2.get_value()); GINAC_ASSERT(idx2.get_value()<=idx3.get_value()); if (CMPINDICES(1,4,6)||CMPINDICES(1,5,7)||CMPINDICES(2,5,6)|| CMPINDICES(3,4,4)||CMPINDICES(3,5,5)) { return _ex1_2(); } else if (CMPINDICES(2,4,7)||CMPINDICES(3,6,6)||CMPINDICES(3,7,7)) { return -_ex1_2(); } else if (CMPINDICES(1,1,8)||CMPINDICES(2,2,8)||CMPINDICES(3,3,8)) { return 1/sqrt(numeric(3)); } else if (CMPINDICES(8,8,8)) { return -1/sqrt(numeric(3)); } else if (CMPINDICES(4,4,8)||CMPINDICES(5,5,8)||CMPINDICES(6,6,8)||CMPINDICES(7,7,8)) { return -1/(2*sqrt(numeric(3))); } return _ex0(); } } break; case color_f: { GINAC_ASSERT(seq.size()==3); const coloridx & idx1=ex_to_coloridx(seq[0]); const coloridx & idx2=ex_to_coloridx(seq[1]); const coloridx & idx3=ex_to_coloridx(seq[2]); // check for three numeric indices if (!(idx1.is_symbolic()||idx2.is_symbolic()||idx3.is_symbolic())) { GINAC_ASSERT(idx1.get_value()<=idx2.get_value()); GINAC_ASSERT(idx2.get_value()<=idx3.get_value()); if (CMPINDICES(1,2,3)) { return _ex1(); } else if (CMPINDICES(1,4,7)||CMPINDICES(2,4,6)|| CMPINDICES(2,5,7)||CMPINDICES(3,4,5)) { return _ex1_2(); } else if (CMPINDICES(1,5,6)||CMPINDICES(3,6,7)) { return -_ex1_2(); } else if (CMPINDICES(4,5,8)||CMPINDICES(6,7,8)) { return sqrt(numeric(3))/2; } else if (CMPINDICES(8,8,8)) { return -1/sqrt(numeric(3)); } else if (CMPINDICES(4,4,8)||CMPINDICES(5,5,8)||CMPINDICES(6,6,8)||CMPINDICES(7,7,8)) { return -1/(2*sqrt(numeric(3))); } return _ex0(); } break; } default: // nothing to evaluate break; } return this->hold(); } // protected int color::compare_same_type(const basic & other) const { GINAC_ASSERT(other.tinfo() == TINFO_color); const color *o = static_cast(&other); if (type==o->type) { if (representation_label==o->representation_label) { return inherited::compare_same_type(other); } return representation_label < o->representation_label ? -1 : 1; } return type < o->type ? -1 : 1; } bool color::is_equal_same_type(const basic & other) const { GINAC_ASSERT(other.tinfo() == TINFO_color); const color *o = static_cast(&other); if (type!=o->type) return false; if (representation_label!=o->representation_label) return false; return inherited::is_equal_same_type(other); } #include ex color::simplify_ncmul(const exvector & v) const { // simplifications: contract delta8_{a,b} where possible // sort delta8,f,d,T(rl=0),T(rl=1),...,ONE(rl=0),ONE(rl=1),... // remove superfluous ONEs // contract indices of delta8_{a,b} if they are different and symbolic exvector v_contracted=v; unsigned replacements; bool something_changed=false; exvector::iterator it=v_contracted.begin(); while (it!=v_contracted.end()) { // process only delta8 objects if (is_ex_exactly_of_type(*it,color) && (ex_to_color(*it).type==color_delta8)) { color & d8=ex_to_nonconst_color(*it); GINAC_ASSERT(d8.seq.size()==2); const coloridx & first_idx=ex_to_coloridx(d8.seq[0]); const coloridx & second_idx=ex_to_coloridx(d8.seq[1]); // delta8_{a,a} should have been contracted in color::eval() GINAC_ASSERT((!first_idx.is_equal(second_idx))||(!first_idx.is_symbolic())); ex saved_delta8=*it; // save to restore it later // try to contract first index replacements=1; if (first_idx.is_symbolic()) { replacements = subs_index_in_exvector(v_contracted,first_idx,second_idx); if (replacements==1) { // not contracted except in itself, restore delta8 object *it=saved_delta8; } else { // a contracted index should occur exactly twice GINAC_ASSERT(replacements==2); *it=_ex1(); something_changed=true; } } // try second index only if first was not contracted if ((replacements==1)&&(second_idx.is_symbolic())) { // first index not contracted, *it is guaranteed to be the original delta8 object replacements = subs_index_in_exvector(v_contracted,second_idx,first_idx); if (replacements==1) { // not contracted except in itself, restore delta8 object *it=saved_delta8; } else { // a contracted index should occur exactly twice GINAC_ASSERT(replacements==2); *it=_ex1(); something_changed=true; } } } ++it; } if (something_changed) { // do more simplifications later return nonsimplified_ncmul(v_contracted); } // there were no indices to contract // sort delta8,f,d,T(rl=0),T(rl=1),...,ONE(rl=0),ONE(rl=1),...,unknown // (if there is at least one unknown object, all Ts will be unknown to not change the order) exvector delta8vec; exvector fvec; exvector dvec; exvectorvector Tvecs; Tvecs.resize(MAX_REPRESENTATION_LABELS); exvectorvector ONEvecs; ONEvecs.resize(MAX_REPRESENTATION_LABELS); exvector unknownvec; split_color_string_in_parts(v,delta8vec,fvec,dvec,Tvecs,ONEvecs,unknownvec); // d_{a,k,l} f_{b,k,l}=0 (includes case a=b) if ((dvec.size()>=1)&&(fvec.size()>=1)) { for (exvector::iterator it1=dvec.begin(); it1!=dvec.end(); ++it1) { for (exvector::iterator it2=fvec.begin(); it2!=fvec.end(); ++it2) { GINAC_ASSERT(is_ex_exactly_of_type(*it1,color)); GINAC_ASSERT(is_ex_exactly_of_type(*it2,color)); const color & col1=ex_to_color(*it1); const color & col2=ex_to_color(*it2); exvector iv_intersect=idx_intersect(col1.seq,col2.seq); if (iv_intersect.size()>=2) return _ex0(); } } } // d_{a,k,l} d_{b,k,l}=5/3 delta8_{a,b} (includes case a=b) if (dvec.size()>=2) { for (exvector::iterator it1=dvec.begin(); it1!=dvec.end()-1; ++it1) { for (exvector::iterator it2=it1+1; it2!=dvec.end(); ++it2) { GINAC_ASSERT(is_ex_exactly_of_type(*it1,color)); GINAC_ASSERT(is_ex_exactly_of_type(*it2,color)); const color & col1=ex_to_color(*it1); const color & col2=ex_to_color(*it2); exvector iv_intersect=idx_intersect(col1.seq,col2.seq); if (iv_intersect.size()>=2) { if (iv_intersect.size()==3) { *it1=numeric(40)/numeric(3); *it2=_ex1(); } else { int sig1, sig2; // unimportant, since symmetric ex idx1=permute_free_index_to_front(col1.seq,iv_intersect,false,&sig1); ex idx2=permute_free_index_to_front(col2.seq,iv_intersect,false,&sig2); *it1=numeric(5)/numeric(3)*color(color_delta8,idx1,idx2); *it2=_ex1(); } return nonsimplified_ncmul(recombine_color_string( delta8vec,fvec,dvec,Tvecs,ONEvecs,unknownvec)); } } } } // f_{a,k,l} f_{b,k,l}=3 delta8_{a,b} (includes case a=b) if (fvec.size()>=2) { for (exvector::iterator it1=fvec.begin(); it1!=fvec.end()-1; ++it1) { for (exvector::iterator it2=it1+1; it2!=fvec.end(); ++it2) { GINAC_ASSERT(is_ex_exactly_of_type(*it1,color)); GINAC_ASSERT(is_ex_exactly_of_type(*it2,color)); const color & col1=ex_to_color(*it1); const color & col2=ex_to_color(*it2); exvector iv_intersect=idx_intersect(col1.seq,col2.seq); if (iv_intersect.size()>=2) { if (iv_intersect.size()==3) { *it1=numeric(24); *it2=_ex1(); } else { int sig1, sig2; ex idx1=permute_free_index_to_front(col1.seq,iv_intersect,true,&sig1); ex idx2=permute_free_index_to_front(col2.seq,iv_intersect,true,&sig2); *it1=numeric(sig1*sig2*5)/numeric(3)*color(color_delta8,idx1,idx2); *it2=_ex1(); } return nonsimplified_ncmul(recombine_color_string( delta8vec,fvec,dvec,Tvecs,ONEvecs,unknownvec)); } } } } // d_{a,b,c} T_b T_c = 5/6 T_a // f_{a,b,c} T_b T_c = 3/2 I T_a for (unsigned rl=0; rl=2)&&((dvec.size()>=1)||(fvec.size()>=1))) { for (exvector::iterator it1=Tvecs[rl].begin(); it1!=Tvecs[rl].end()-1; ++it1) { exvector iv; GINAC_ASSERT(is_ex_exactly_of_type(*it1,color)&&ex_to_color(*it1).type==color_T); GINAC_ASSERT(is_ex_exactly_of_type(*(it1+1),color)&&ex_to_color(*(it1+1)).type==color_T); iv.push_back(ex_to_color(*it1).seq[0]); iv.push_back(ex_to_color(*(it1+1)).seq[0]); // d_{a,b,c} T_b T_c = 5/6 T_a for (exvector::iterator it2=dvec.begin(); it2!=dvec.end(); ++it2) { GINAC_ASSERT(is_ex_exactly_of_type(*it2,color)&&ex_to_color(*it2).type==color_d); const color & dref=ex_to_color(*it2); exvector iv_intersect=idx_intersect(dref.seq,iv); if (iv_intersect.size()==2) { int sig; // unimportant, since symmetric ex free_idx=permute_free_index_to_front(dref.seq,iv,false,&sig); *it1=color(color_T,free_idx,rl); *(it1+1)=color(color_ONE,rl); *it2=numeric(5)/numeric(6); return nonsimplified_ncmul(recombine_color_string( delta8vec,fvec,dvec,Tvecs,ONEvecs,unknownvec)); } } // f_{a,b,c} T_b T_c = 3/2 I T_a for (exvector::iterator it2=fvec.begin(); it2!=fvec.end(); ++it2) { GINAC_ASSERT(is_ex_exactly_of_type(*it2,color)&&ex_to_color(*it2).type==color_f); const color & fref=ex_to_color(*it2); exvector iv_intersect=idx_intersect(fref.seq,iv); if (iv_intersect.size()==2) { int sig; ex free_idx=permute_free_index_to_front(fref.seq,iv,true,&sig); *it1=color(color_T,free_idx,rl); *(it1+1)=color(color_ONE,rl); *it2=numeric(sig*3)/numeric(2)*I; return nonsimplified_ncmul(recombine_color_string( delta8vec,fvec,dvec,Tvecs,ONEvecs,unknownvec)); } } } } } // clear all ONEs when there is at least one corresponding color_T // in this representation, retain one ONE otherwise for (unsigned rl=0; rl=2) { for (unsigned i=0; i counter; counter.resize(iv_double.size()); int l; for (l=0; unsigned(l)=0)&&((++counter[l])>(int)COLOR_EIGHT)) { counter[l]=1; l--; } if (l<2) { cout << counter[0] << counter[1] << endl; } if (l<0) break; } return sum; } void append_exvector_to_exvector(exvector & dest, const exvector & source) { for (exvector::const_iterator cit=source.begin(); cit!=source.end(); ++cit) { dest.push_back(*cit); } } #ifndef NO_NAMESPACE_GINAC } // namespace GiNaC #endif // ndef NO_NAMESPACE_GINAC