diff options
Diffstat (limited to 'src/mean.c')
-rw-r--r-- | src/mean.c | 141 |
1 files changed, 109 insertions, 32 deletions
@@ -1,5 +1,5 @@ /* -Copyright 2015 Ian Jauslin +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. @@ -30,6 +30,7 @@ As of version 1.0, the mean of a monomial is computed directly #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){ @@ -61,10 +62,79 @@ int mean(Int_Array monomial, Polynomial* out, Fields_Table fields, Polynomial_Ma // 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<n;i++){ + a=intlist_find_err(propagator.indices, propagator.length, internal_plus.values[i]); + for(j=0;j<n;j++){ + b=intlist_find_err(propagator.indices, propagator.length, -internal_minus.values[j]); + // ignore 0 + if(propagator.matrix[a][b].length!=0){ + // check whether the fields are Fermions, and whether the entry is a number + if(is_fermion(internal_plus.values[i], fields)==0 || is_fermion(internal_minus.values[j], fields)==0 || polynomial_is_number(propagator.matrix[a][b])==0){ + free_Number_Matrix(M); + return(-1); + } + + number_add_chain(propagator.matrix[a][b].nums[0], M.matrix[i]+j); + } + } + } + + // compute determinant + determinant_inplace(M, out); + + number_Qprod_chain(quot(sign,1), out); + + free_Number_Matrix(M); + + return(0); +} + + +// compute the mean of a monomial by summing over permutations +int mean_permutations(Int_Array internal_plus, Int_Array internal_minus, Polynomial* out, Polynomial_Matrix propagator, Fields_Table fields){ int n=internal_minus.length; // pairing as an array of positions int* pairing=calloc(n,sizeof(int)); @@ -118,7 +188,7 @@ int mean_internal(Int_Array internal_plus, Int_Array internal_minus, Polynomial* pairing_sign=permutation_signature(pairing,n); } - // only simplify in mean_symbols + // only simplify in mean_virtual_fields polynomial_prod_chain_nosimplify(num_summed,out,fields); free_Polynomial(num_summed); free(pairing); @@ -346,10 +416,10 @@ int get_internals(Int_Array monomial, Int_Array* internal_plus, Int_Array* inter } -// compute the mean of a monomial containing symbolic expressions +// compute the mean of a monomial containing virtual fields // keep track of which means were already computed -int mean_symbols(Int_Array monomial, Polynomial* output, Fields_Table fields, Polynomial_Matrix propagator, Groups groups, Identities* computed){ - Int_Array symbol_list; +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; @@ -375,43 +445,43 @@ int mean_symbols(Int_Array monomial, Polynomial* output, Fields_Table fields, Po } } - init_Int_Array(&symbol_list, monomial.length); + init_Int_Array(&virtual_field_list, monomial.length); init_Int_Array(&base_monomial, monomial.length); - // generate symbols list + // generate virtual_fields list for(i=0;i<monomial.length;i++){ - if(field_type(monomial.values[i], fields)==FIELD_SYMBOL){ - int_array_append(intlist_find_err(fields.symbols.indices, fields.symbols.length, monomial.values[i]), &symbol_list); + if(field_type(monomial.values[i], fields)==FIELD_VIRTUAL){ + int_array_append(intlist_find_err(fields.virtual_fields.indices, fields.virtual_fields.length, monomial.values[i]), &virtual_field_list); } else{ int_array_append(monomial.values[i], &base_monomial); } } - power=symbol_list.length; + power=virtual_field_list.length; // trivial case if(power==0){ mean(monomial, &mean_num, fields, propagator); polynomial_concat_noinit(mean_num, output); - free_Int_Array(symbol_list); + free_Int_Array(virtual_field_list); free_Int_Array(base_monomial); return(0); } else{ // initialize current term to a position that has no repetitions current_term=calloc(power,sizeof(int)); - exists_next=init_prod(current_term, symbol_list, fields, power, base_monomial)+1; + exists_next=init_prod(current_term, virtual_field_list, fields, power, base_monomial)+1; } - // loop over terms; the loop stops when all the pointers are at the end of the first symbol + // loop over terms; the loop stops when all the pointers are at the end of the first virtual field while(exists_next==1){ // construct monomial int_array_cpy(base_monomial, &tmp_monomial); tmp_num=number_one(); for(i=0;i<power;i++){ - int_array_concat(fields.symbols.expr[symbol_list.values[i]].monomials[current_term[i]], &tmp_monomial); - number_prod_chain(fields.symbols.expr[symbol_list.values[i]].nums[current_term[i]], &tmp_num); + int_array_concat(fields.virtual_fields.expr[virtual_field_list.values[i]].monomials[current_term[i]], &tmp_monomial); + number_prod_chain(fields.virtual_fields.expr[virtual_field_list.values[i]].nums[current_term[i]], &tmp_num); } // check whether the monomial vanishes if(check_monomial_match(tmp_monomial, fields)==1){ @@ -432,7 +502,7 @@ int mean_symbols(Int_Array monomial, Polynomial* output, Fields_Table fields, Po free_Int_Array(tmp_monomial); // next term - exists_next=next_prod(current_term, symbol_list, fields, power, base_monomial)+1; + exists_next=next_prod(current_term, virtual_field_list, fields, power, base_monomial)+1; // simplfiy every 25 steps (improves both memory usage and performance) @@ -451,13 +521,13 @@ int mean_symbols(Int_Array monomial, Polynomial* output, Fields_Table fields, Po // free memory free(current_term); - free_Int_Array(symbol_list); + free_Int_Array(virtual_field_list); free_Int_Array(base_monomial); return(0); } // first term in product with no repetitions -int init_prod(int* current_term, Int_Array symbol_list, Fields_Table fields, int power, Int_Array base_monomial){ +int init_prod(int* current_term, Int_Array virtual_field_list, Fields_Table fields, int power, Int_Array base_monomial){ // index we want to increment int move=0; // tmp monomial @@ -474,7 +544,7 @@ int init_prod(int* current_term, Int_Array symbol_list, Fields_Table fields, int // loop until move is out of range while(move>=0 && move<power){ // move - current_term[move]=next_term_norepeat(current_term[move], fields.symbols.expr[symbol_list.values[move]], &monomial, fields); + current_term[move]=next_term_norepeat(current_term[move], fields.virtual_fields.expr[virtual_field_list.values[move]], &monomial, fields); // if the next term does not exist, then move previous index if(current_term[move]==-1){ move--; @@ -495,7 +565,7 @@ int init_prod(int* current_term, Int_Array symbol_list, Fields_Table fields, int } // next term in product with no repetitions -int next_prod(int* current_term, Int_Array symbol_list, Fields_Table fields, int power, Int_Array base_monomial){ +int next_prod(int* current_term, Int_Array virtual_field_list, Fields_Table fields, int power, Int_Array base_monomial){ // index we want to increment int move=power-1; // tmp monomial @@ -506,13 +576,13 @@ int next_prod(int* current_term, Int_Array symbol_list, Fields_Table fields, int init_Int_Array(&monomial, base_monomial.length+5*power); int_array_cpy_noinit(base_monomial, &monomial); for(i=0;i<=move;i++){ - int_array_concat(fields.symbols.expr[symbol_list.values[i]].monomials[current_term[i]],&monomial); + int_array_concat(fields.virtual_fields.expr[virtual_field_list.values[i]].monomials[current_term[i]],&monomial); } // loop until move is out of range while(move>=0 && move<power){ // move - current_term[move]=next_term_norepeat(current_term[move], fields.symbols.expr[symbol_list.values[move]], &monomial, fields); + current_term[move]=next_term_norepeat(current_term[move], fields.virtual_fields.expr[virtual_field_list.values[move]], &monomial, fields); // if the next term does not exist, then move previous index if(current_term[move]==-1){ move--; @@ -623,13 +693,13 @@ int mean_groups(Int_Array monomial, Polynomial* output, Fields_Table fields, Pol int group=-2; int next_group=-2; Polynomial tmp_poly; - int sign; + int sign=1; init_Polynomial(output, MONOMIAL_SIZE); - // check whether there are symbols - // IMPORTANT: the symbols must be at the end of the monomial - if(monomial.length==0 || field_type(monomial.values[monomial.length-1], fields)!=FIELD_SYMBOL){ + // check whether there are virtual fields + // IMPORTANT: the virtual fields must be at the end of the monomial + if(monomial.length==0 || field_type(monomial.values[monomial.length-1], fields)!=FIELD_VIRTUAL){ // mean mean(monomial, &num_mean, fields, propagator); // add to output @@ -650,7 +720,7 @@ int mean_groups(Int_Array monomial, Polynomial* output, Fields_Table fields, Pol } // if group changes, take mean if((i>0 && next_group!=group) || i==monomial.length){ - mean_symbols(tmp_monomial, &tmp_poly, fields, propagator, groups, computed); + mean_virtual_fields(tmp_monomial, &tmp_poly, fields, propagator, groups, computed); // if zero if(polynomial_is_zero(tmp_poly)==1){ // set output to 0 @@ -702,10 +772,11 @@ struct mean_args{ Fields_Table fields; Polynomial_Matrix propagator; Groups groups; + int print_progress; }; // multithreaded -int polynomial_mean_multithread(Polynomial* polynomial, Fields_Table fields, Polynomial_Matrix propagator, Groups groups, int threads){ +int polynomial_mean_multithread(Polynomial* polynomial, Fields_Table fields, Polynomial_Matrix propagator, Groups groups, int threads, int print_progress){ int i; Polynomial thread_polys[threads]; pthread_t thread_ids[threads]; @@ -720,11 +791,15 @@ int polynomial_mean_multithread(Polynomial* polynomial, Fields_Table fields, Pol args[i].fields=fields; args[i].propagator=propagator; args[i].groups=groups; + args[i].print_progress=print_progress; } // split polynomial + // randomly choose the thread + // see random number generator + srand(time(NULL)); for(i=0;i<len;i++){ - polynomial_append((*polynomial).monomials[i], (*polynomial).factors[i], (*polynomial).nums[i], thread_polys+(i % threads)); + polynomial_append((*polynomial).monomials[i], (*polynomial).factors[i], (*polynomial).nums[i], thread_polys+(rand() % threads)); } // start threads @@ -750,12 +825,12 @@ int polynomial_mean_multithread(Polynomial* polynomial, Fields_Table fields, Pol // mean for one of the threads void* polynomial_mean_thread(void* mean_args){ struct mean_args *args=mean_args; - polynomial_mean((*args).polynomial,(*args).fields,(*args).propagator,(*args).groups); + polynomial_mean((*args).polynomial,(*args).fields,(*args).propagator,(*args).groups, (*args).print_progress); return(NULL); } // single threaded version -int polynomial_mean(Polynomial* polynomial, Fields_Table fields, Polynomial_Matrix propagator, Groups groups){ +int polynomial_mean(Polynomial* polynomial, Fields_Table fields, Polynomial_Matrix propagator, Groups groups, int print_progress){ int i,j; Polynomial output; Polynomial tmp_poly; @@ -769,7 +844,9 @@ int polynomial_mean(Polynomial* polynomial, Fields_Table fields, Polynomial_Matr // mean of each monomial for(i=0;i<(*polynomial).length;i++){ - fprintf(stderr,"computing %d of %d means\n",i,(*polynomial).length-1); + if(print_progress==1){ + fprintf(stderr,"computing %d of %d means\n",i,(*polynomial).length-1); + } mean_groups((*polynomial).monomials[i], &tmp_poly, fields, propagator, groups, &computed); // write factors |