/** @file color.cpp * * Implementation of GiNaC's color objects. * No real implementation yet, to be done. */ /* * GiNaC Copyright (C) 1999 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 "debugmsg.h" namespace GiNaC { ////////// // 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(color const & other) { debugmsg("color copy constructor",LOGLEVEL_CONSTRUCT); copy (other); } color const & color::operator=(color const & other) { debugmsg("color operator=",LOGLEVEL_ASSIGNMENT); if (this != &other) { destroy(1); copy(other); } return *this; } // protected void color::copy(color const & other) { indexed::copy(other); type=other.type; representation_label=other.representation_label; } void color::destroy(bool call_parent) { if (call_parent) { indexed::destroy(call_parent); } } ////////// // other constructors ////////// // protected color::color(color_types const t, unsigned const rl) : type(t), representation_label(rl) { debugmsg("color constructor from color_types,unsigned",LOGLEVEL_CONSTRUCT); GINAC_ASSERT(representation_labelhold(); } // protected int color::compare_same_type(basic const & 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 indexed::compare_same_type(other); } return representation_label < o->representation_label ? -1 : 1; } return type < o->type ? -1 : 1; } bool color::is_equal_same_type(basic const & 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 indexed::is_equal_same_type(other); } #include ex color::simplify_ncmul(exvector const & 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); coloridx const & first_idx=ex_to_coloridx(d8.seq[0]); coloridx const & 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=exONE(); 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=exONE(); 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; vector Tvecs; Tvecs.resize(MAX_REPRESENTATION_LABELS); vector 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)); color const & col1=ex_to_color(*it1); color const & col2=ex_to_color(*it2); exvector iv_intersect=idx_intersect(col1.seq,col2.seq); if (iv_intersect.size()>=2) return exZERO(); } } } // 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)); color const & col1=ex_to_color(*it1); color const & 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=exONE(); } 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=exONE(); } 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)); color const & col1=ex_to_color(*it1); color const & 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=exONE(); } 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=exONE(); } 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); color const & 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); color const & 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 & Tvecs, vector & ONEvecs, exvector & unknownvec) { // if not all elements are of type color, put all Ts in unknownvec to // retain the ordering bool all_color=true; for (exvector::const_iterator cit=v.begin(); cit!=v.end(); ++cit) { if (!is_ex_exactly_of_type(*cit,color)) { all_color=false; break; } } for (exvector::const_iterator cit=v.begin(); cit!=v.end(); ++cit) { if (is_ex_exactly_of_type(*cit,color)) { switch (ex_to_color(*cit).type) { case color::color_delta8: delta8vec.push_back(*cit); break; case color::color_f: fvec.push_back(*cit); break; case color::color_d: dvec.push_back(*cit); break; case color::color_T: GINAC_ASSERT(ex_to_color(*cit).representation_label & Tvecs, vector & ONEvecs, exvector & unknownvec) { unsigned sz=delta8vec.size()+fvec.size()+dvec.size()+unknownvec.size(); for (unsigned rl=0; rl Tvecs; Tvecs.resize(MAX_REPRESENTATION_LABELS); vector ONEvecs; ONEvecs.resize(MAX_REPRESENTATION_LABELS); exvector unknownvec; split_color_string_in_parts(ex_to_ncmul(e).get_factors(),delta8vec,fvec,dvec,Tvecs,ONEvecs,unknownvec); // search for T_k S T_k (=1/2 Tr(S) - 1/6 S) 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, exvector const & source) { for (exvector::const_iterator cit=source.begin(); cit!=source.end(); ++cit) { dest.push_back(*cit); } } } // namespace GiNaC