- // 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<MAX_REPRESENTATION_LABELS; ++rl) {
- if ((Tvecs[rl].size()>=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<MAX_REPRESENTATION_LABELS; ++rl) {
- if (Tvecs[rl].size()!=0) {
- ONEvecs[rl].clear();
- } else if (ONEvecs[rl].size()!=0) {
- ONEvecs[rl].clear();
- ONEvecs[rl].push_back(color(color_ONE,rl));
- }
- }
-
- // return a sorted vector
- return simplified_ncmul(recombine_color_string(delta8vec,fvec,dvec,Tvecs,
- ONEvecs,unknownvec));