/* Copyright 2015-2022 Ian Jauslin Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* As of version 1.0, the mean of a monomial is computed directly */ #include "mean.h" #include #include #include #include "definitions.cpp" #include "tools.h" #include "polynomial.h" #include "rational.h" #include "array.h" #include "fields.h" #include "number.h" #include "determinant.h" // mean of a monomial int mean(Int_Array monomial, Polynomial* out, Fields_Table fields, Polynomial_Matrix propagator){ int sign=1; // +/- internal fields Int_Array internal_plus; Int_Array internal_minus; // init out *out=polynomial_one(); // sort first monomial_sort(monomial, fields, &sign); polynomial_multiply_Qscalar(*out, quot(sign,1)); // get internals // (*out).monomials is the first element of out but it only has 1 element // first, free (*out).monomials[0] free_Int_Array((*out).monomials[0]); get_internals(monomial, &internal_plus, &internal_minus, (*out).monomials, fields); if(internal_plus.length>0 && internal_minus.length>0){ mean_internal(internal_plus, internal_minus, out, propagator, fields); } free_Int_Array(internal_plus); free_Int_Array(internal_minus); return(0); } // compute the mean of a monomial of internal fields (with split + and -) int mean_internal(Int_Array internal_plus, Int_Array internal_minus, Polynomial* out, Polynomial_Matrix propagator, Fields_Table fields){ int ret; Number num; if(internal_plus.length!=internal_minus.length){ fprintf(stderr,"error: monomial contains unmatched +/- fields\n"); exit(-1); } ret=mean_determinant(internal_plus, internal_minus, &num, propagator, fields); // cannot compute the mean as a determinant, use permutations // can be because some fields are not Fermions // can be because the propagator has non-numeric values (inverting polynomials is not implemented, and would be required for the computation of the determinant) if(ret==-1){ mean_permutations(internal_plus, internal_minus, out, propagator, fields); } else{ polynomial_multiply_scalar(*out, num); free_Number(num); } return(0); } // compute the mean of a monomial by computing a determinant // can only be used if all of the propagators are numbers int mean_determinant(Int_Array internal_plus, Int_Array internal_minus, Number* out, Polynomial_Matrix propagator, Fields_Table fields){ Number_Matrix M; int n=internal_minus.length; int i,j; int a,b; int sign; init_Number_Matrix(&M,n); // extra sign: the monomial is sorted in such a way that minus fields are on the left of plus fields, but the determinant formula requires the fields to be alternated +- if((n+1)/2%2==1){ sign=-1; } else{ sign=1; } // construct matrix for(i=0;i=0 && move=0 && move=0 && start=0;i--){ // move i-th mask[pairing[i]]=0; // search for next possible position for(j=pairing[i]+1;j=n){ break; } } } } // if the next position was found, then don't try to move the previous pairings break; } // if no next position is found, store the pairing outside the array (so the algorithm stops when the first pairing is outside the array) else{ pairing[i]=n; } } } number_prod_chain(num_summed,outnum); free_Number(num_summed); free(pairing); free(mask); return(0); } */ // get lists of internal fields from a monomial (separate + and -) // requires the monomial to be sorted (for the sign to be correct) int get_internals(Int_Array monomial, Int_Array* internal_plus, Int_Array* internal_minus, Int_Array* others, Fields_Table fields){ int i; init_Int_Array(internal_plus, monomial.length); init_Int_Array(internal_minus, monomial.length); init_Int_Array(others, monomial.length); for (i=0;i=0){ // split +/- fields if(monomial.values[i]>0){ int_array_append(monomial.values[i],internal_plus); } else{ int_array_append(monomial.values[i],internal_minus); } } else{ int_array_append(monomial.values[i], others); } } return(0); } // compute the mean of a monomial containing virtual fields // keep track of which means were already computed int mean_virtual_fields(Int_Array monomial, Polynomial* output, Fields_Table fields, Polynomial_Matrix propagator, Groups groups, Identities* computed){ Int_Array virtual_field_list; int i; int power; int* current_term; Polynomial mean_num; Int_Array tmp_monomial; Number tmp_num; Int_Array base_monomial; int sign; // whether or not the next term exists int exists_next=0; // simplify polynomial periodically int simplify_freq=1; Polynomial mean_poly; init_Polynomial(output, POLY_SIZE); // check whether the mean was already computed for(i=0;i<(*computed).length;i++){ if(int_array_cmp((*computed).lhs[i], monomial)==0){ // write polynomial polynomial_concat((*computed).rhs[i], output); return(0); } } init_Int_Array(&virtual_field_list, monomial.length); init_Int_Array(&base_monomial, monomial.length); // generate virtual_fields list for(i=0;i=0 && move=0 && move=0 && start0){ sign=1; monomial_sort_groups(monomial, fields, groups, &sign); } // construct groups and take mean init_Int_Array(&tmp_monomial, MONOMIAL_SIZE); for(i=0;i<=monomial.length;i++){ // new group if(i0 && next_group!=group) || i==monomial.length){ mean_virtual_fields(tmp_monomial, &tmp_poly, fields, propagator, groups, computed); // if zero if(polynomial_is_zero(tmp_poly)==1){ // set output to 0 free_Polynomial(*output); init_Polynomial(output, 1); free_Polynomial(tmp_poly); break; } // add to output if(polynomial_is_zero(*output)==1){ polynomial_concat(tmp_poly, output); } else{ polynomial_prod_chain_nosimplify(tmp_poly, output, fields); } free_Polynomial(tmp_poly); // reset tmp_monomial free_Int_Array(tmp_monomial); init_Int_Array(&tmp_monomial, MONOMIAL_SIZE); } // add to monomial if(i