Package madgraph :: Package various :: Module q_polynomial
[hide private]
[frames] | no frames]

Source Code for Module madgraph.various.q_polynomial

  1  import array 
  2  import copy 
  3  import math 
4 5 -class PolynomialError(Exception): pass
6
7 -def get_number_of_coefs_for_rank(r):
8 """ Returns the number of independent coefficients there is in a 9 fully symmetric tensor of rank r """ 10 return sum([((3+ri)*(2+ri)*(1+ri))/6 for ri in range(0,r+1)])
11
12 -class Polynomial(object):
13 """ A class to represent a polynomial in the loop momentum (4-vector) q 14 and how the symmetrized coefficients are ordered. The ordering rule 15 correspond to what is presented in Eq. C.15 of arxiv:hep-ph/1405.0301""" 16
17 - def __init__(self, rank):
18 19 assert rank > -1, "The rank of a q-polynomial should be 0 or positive" 20 self.rank=rank 21 self.init_coef_list()
22
23 - def init_coef_list(self):
24 """ Creates a list whose elements are arrays being the coefficient 25 indices. We order this list according to the algorithm in 26 get_coef_position. This coef_list can then be used for the function 27 get_coef_at_position() 28 """ 29 30 self.coef_list=[None,]*get_number_of_coefs_for_rank(self.rank) 31 32 PNO = Polynomial_naive_ordering(self.rank) 33 34 for coef in PNO.coef_list: 35 self.coef_list[self.get_coef_position(list(coef))]=coef
36
37 - def get_coef_position(self, indices_list):
38 """ Returns the canonical position for a coefficient characterized 39 by the value of the indices of the loop momentum q it multiplies, 40 that is for example C_01032 multiplying q_0*q_1*q_0*q_3*q_2. 41 We assume that the explicit construction of the position below is 42 faster than a lookup in a table""" 43 44 fact = math.factorial 45 46 if len(indices_list)==0: 47 return 0 48 49 res = get_number_of_coefs_for_rank(len(indices_list)-1) 50 51 new_indices_list = copy.copy(indices_list) 52 new_indices_list.sort() 53 54 for i, ind in enumerate(new_indices_list): 55 if ind>0: 56 res = res + (fact(ind+i)/(fact(i+1)*fact(ind - 1))) 57 58 return res
59
60 - def get_coef_at_position(self, pos):
61 """ Returns the coefficient at position pos in the one dimensional 62 vector """ 63 return list(self.coef_list[pos])
64
65 -class Polynomial_naive_ordering(object):
66 """ A class to represent a polynomial in the loop momentum (4-vector) q""" 67
68 - def __init__(self, rank):
69 70 assert rank > -1, "The rank of a q-polynomial should be 0 or positive" 71 self.rank=rank 72 self.init_coef_list()
73
74 - def init_coef_list(self):
75 """ Creates a list whose elements are arrays being the coefficient 76 indices sorted in growing order and the value is their position in a 77 one-dimensional vector. For example the position of the coefficient 78 C_01032 will be placed in the list under array.array('i',(0,0,1,3,2)). 79 """ 80 self.coef_list=[] 81 self.coef_list.append(array.array('i',())) 82 83 if self.rank==0: 84 return 85 86 tmp_coef_list=[array.array('i',(0,)),array.array('i',(1,)), 87 array.array('i',(2,)),array.array('i',(3,))] 88 self.coef_list.extend(tmp_coef_list) 89 90 for i in range(1,self.rank): 91 new_tmp_coef_list=[] 92 for coef in tmp_coef_list: 93 for val in range(coef[-1],4): 94 new_coef=copy.copy(coef) 95 new_coef.append(val) 96 new_tmp_coef_list.append(new_coef) 97 tmp_coef_list=new_tmp_coef_list 98 self.coef_list.extend(tmp_coef_list)
99
100 - def get_coef_position(self, indices_list):
101 """ Returns the canonical position for a coefficient characterized 102 by the value of the indices of the loop momentum q it multiplies, 103 that is for example C_01032 multiplying q_0*q_1*q_0*q_3*q_2 """ 104 105 new_indices_list=copy.copy(indices_list) 106 new_indices_list.sort() 107 try: 108 return self.coef_list.index(array.array('i',new_indices_list)) 109 except ValueError: 110 raise PolynomialError,\ 111 "The index %s looked for could not be found"%str(indices_list)
112
113 - def get_coef_at_position(self, pos):
114 """ Returns the coefficient at position pos in the one dimensional 115 vector """ 116 return list(self.coef_list[pos])
117
118 -class PolynomialRoutines(object):
119 """ The mother class to output the polynomial subroutines """ 120
121 - def __init__(self, max_rank, coef_format='complex*16', sub_prefix='' 122 ,line_split=30):
123 124 self.coef_format=coef_format 125 self.sub_prefix=sub_prefix 126 if coef_format=='complex*16': 127 self.rzero='0.0d0' 128 self.czero='(0.0d0,0.0d0)' 129 elif coef_format=='complex*32': 130 self.rzero='0.0e0_16' 131 self.czero='CMPLX(0.0e0_16,0.0e0_16,KIND=16)' 132 else: 133 self.rzero='0.0e0' 134 self.czero='(0.0e0,0.0e0)' 135 self.line_split=line_split 136 if max_rank<0: 137 raise PolynomialError, \ 138 "The rank of a q-polynomial should be 0 or positive" 139 self.max_rank=max_rank 140 self.pq=Polynomial(max_rank)
141
142 -class FortranPolynomialRoutines(PolynomialRoutines):
143 """ A daughter class to output the subroutine in the fortran format""" 144 145
146 - def write_pjfry_mapping(self):
147 """ Returns a fortran subroutine which fills in the array of integral reduction 148 coefficients following MadLoop standards using pjfry++ coefficients.""" 149 150 # THE OUTPUT OF COEFS FROM PJFRY++ IS 151 # RANK=0: (,) 152 # RANK=1: (0,),(1,),(2,),(3,) 153 # RANK=2: (0,0),(0,1),(1,1),(0,2),(1,2),(2,2),(0,3),(1,3),(2,3),(3,3) 154 # ... 155 # THE OUTPUT OF COEFS FROM MADLOOP IS 156 # RANK=0: (,) 157 # RANK=1: (0,),(1,),(2,),(3,) 158 # RANK=2: (0,0),(0,1),(0,2),(0,3),(1,1),(2,1),(3,1),(2,2),(2,3),(3,3) 159 # ... 160 161 162 # Helper function 163 def format_power(pow): 164 b, e = pow 165 166 if e == 1: 167 return str(b) 168 else: 169 return "%s^%d" % (b, e)
170 171 172 def get_coef_position(indices_list): 173 new_indices_list=copy.copy(indices_list) 174 new_indices_list.sort() 175 r=len(new_indices_list) 176 if r == 0: 177 pos=0 178 else: 179 pos=get_number_of_coefs_for_rank(r-1) 180 for i,mu in enumerate(new_indices_list): 181 num = mu 182 den = 1 183 if mu > 0 and i > 0: 184 for j in range(2,i+2): 185 num *= (mu+j-1) 186 den *= j 187 pos += num/den 188 return pos
189 190 lines = [] 191 lines.append( 192 """SUBROUTINE %(sub_prefix)sCONVERT_PJFRY_COEFFS(RANK,PJCOEFS,TIRCOEFS) 193 C GLOABLE VARIABLES 194 include 'coef_specs.inc' 195 C ARGUMENTS 196 INTEGER RANK 197 %(coef_format)s PJCOEFS(0:LOOP_MAXCOEFS-1,3) 198 %(coef_format)s TIRCOEFS(0:LOOP_MAXCOEFS-1,3)""" 199 %{'sub_prefix':self.sub_prefix,'coef_format':self.coef_format}) 200 201 for R in range(self.max_rank+1): 202 Ncoeff=((3+R)*(2+R)*(1+R))/6 203 if R == 0: 204 offset=0 205 else: 206 offset=get_number_of_coefs_for_rank(R-1) 207 for i in range(offset,Ncoeff+offset): 208 indices_list=self.pq.get_coef_at_position(i) 209 sindices = map(lambda i: "q(%d)" % i, indices_list) 210 coeff_list = [] 211 for j in range(4): 212 qvalue = "q(%d)"%j 213 qpow = sindices.count(qvalue) 214 if qpow > 0: 215 coeff_list.append(format_power([qvalue,qpow])) 216 217 if not coeff_list: 218 coeff_str = "1" 219 else: 220 coeff_str = "*".join(coeff_list) 221 222 pjpos = get_coef_position(indices_list) 223 lines.append("c Reduction Coefficient %s"%coeff_str) 224 lines.append('TIRCOEFS(%d,1:3)=PJCOEFS(%d,1:3)'%(i,pjpos)) 225 lines.append('IF(RANK.LE.%d)RETURN'%R) 226 227 lines.append('end') 228 229 return '\n'.join(lines) 230
231 - def write_iregi_mapping(self):
232 """ Returns a fortran subroutine which fills in the array of integral reduction 233 coefficients following MadLoop standards using IREGI coefficients.""" 234 235 # THE OUTPUT OF COEFS FROM IREGI IS 236 # RANK=0: (,) 237 # RANK=1: (0,),(1,),(2,),(3,) 238 # RANK=2: (0,0),(0,1),(0,2),(0,3),(1,1),(2,1),(3,1),(2,2),(2,3),(3,3) 239 # ... 240 241 # Helper function 242 def format_power(pow): 243 b, e = pow 244 245 if e == 1: 246 return str(b) 247 else: 248 return "%s^%d" % (b, e)
249 250 lines = [] 251 lines.append( 252 """SUBROUTINE %(sub_prefix)sCONVERT_IREGI_COEFFS(RANK,IREGICOEFS,TIRCOEFS) 253 C GLOABLE VARIABLES 254 include 'coef_specs.inc' 255 C ARGUMENTS 256 INTEGER RANK 257 %(coef_format)s IREGICOEFS(0:LOOP_MAXCOEFS-1,3) 258 %(coef_format)s TIRCOEFS(0:LOOP_MAXCOEFS-1,3)""" 259 %{'sub_prefix':self.sub_prefix,'coef_format':self.coef_format}) 260 261 iregi_gen = FromIREGIFortranCodeGenerator(self.max_rank) 262 for R in range(self.max_rank+1): 263 Ncoeff=((3+R)*(2+R)*(1+R))/6 264 if R == 0: 265 offset=0 266 else: 267 offset=get_number_of_coefs_for_rank(R-1) 268 for i in range(offset,Ncoeff+offset): 269 indices_list=self.pq.get_coef_at_position(i) 270 sindices = map(lambda i: "q(%d)" % i, indices_list) 271 coeff_list = [] 272 for j in range(4): 273 qvalue = "q(%d)"%j 274 qpow = sindices.count(qvalue) 275 if qpow > 0: 276 coeff_list.append(format_power([qvalue,qpow])) 277 278 if not coeff_list: 279 coeff_str = "1" 280 else: 281 coeff_str = "*".join(coeff_list) 282 283 iregipos = iregi_gen.get_coef_position(indices_list) 284 lines.append("c Reduction Coefficient %s"%coeff_str) 285 lines.append('TIRCOEFS(%d,1:3)=IREGICOEFS(%d,1:3)'%(i,iregipos)) 286 lines.append('IF(RANK.LE.%d)RETURN'%R) 287 lines.append('end') 288 289 return '\n'.join(lines) 290
291 - def write_golem95_mapping(self):
292 """ Returns a fortran subroutine which fills in the array of tensorial 293 coefficients following golem95 standards using MadLoop coefficients.""" 294 295 subroutines = [] 296 297 # Set number of space-time dimensions to 4 here 298 d = 4 299 golem_max_rank = 6 300 301 # First generate the block_info which contains information about the 302 # about the block structure of the system 303 block_info = {} 304 for R in range(1,self.max_rank+1): 305 for k in range(1,min(R,d)+1): 306 LHS, RHS, lst, dic = \ 307 FromGolem95FortranCodeGenerator.generate_equations(R, k) 308 block_info[(R,k)] = (lst, dic) 309 310 # Helper function 311 def format_power(pow): 312 b, e = pow 313 314 if e == 1: 315 return str(b) 316 else: 317 return "%s^%d" % (b, e)
318 319 # Write out one subroutine per rank 320 for R in range(golem_max_rank+1): 321 322 lines=[] 323 324 if R==0: 325 lines.append( 326 """SUBROUTINE %(sub_prefix)sFILL_GOLEM_COEFFS_0(ML_COEFS,GOLEM_COEFS) 327 use precision_golem, only: ki 328 include 'coef_specs.inc' 329 %(coef_format)s ML_COEFS(0:LOOP_MAXCOEFS-1) 330 complex(ki) GOLEM_COEFS""" 331 %{'sub_prefix':self.sub_prefix,'coef_format':self.coef_format}) 332 lines.append("GOLEM_COEFS=ML_COEFS(0)") 333 lines.append("end") 334 subroutines.append('\n'.join(lines)) 335 continue 336 337 # Start by writing out the header: 338 lines.append( 339 """SUBROUTINE %(sub_prefix)sFILL_GOLEM_COEFFS_%(rank)d(ML_COEFS,GOLEM_COEFS) 340 use tens_rec, only: coeff_type_%(rank)d 341 include 'coef_specs.inc' 342 %(coef_format)s ML_COEFS(0:LOOP_MAXCOEFS-1) 343 type(coeff_type_%(rank)d) GOLEM_COEFS""" 344 %{'sub_prefix':self.sub_prefix,'rank':R, 345 'coef_format':self.coef_format}) 346 347 if R > self.max_rank: 348 lines.append('C Dummy routine for %(sub_prefix)sFILL_GOLEM_COEFS_%(rank)d'\ 349 %{'sub_prefix':self.sub_prefix,'rank':R, 350 'coef_format':self.coef_format}) 351 lines.append("STOP 'ERROR: %d > %d'"%(R,self.max_rank)) 352 lines.append('end') 353 subroutines.append('\n'.join(lines)) 354 continue 355 356 # The constant coefficient is treated separately 357 lines.append("c Constant coefficient ") 358 lines.append("GOLEM_COEFS%%c0=ML_COEFS(%d)"\ 359 %self.pq.get_coef_position([])) 360 361 # Now write out the explicit mapping 362 for k in range(1,min(R,d)+1): 363 lst, dic = block_info[(R,k)] 364 dim = len(lst) 365 lab = 0 366 for indices in FromGolem95FortranCodeGenerator.select(range(d), k): 367 lab += 1 368 sindices = map(lambda i: "q(%d)" % i, indices) 369 for i in range(dim): 370 coeff_str = "*".join(map(format_power,zip(sindices, lst[i]))) 371 ML_indices = sum( 372 [[ind]*lst[i][j] for j, ind in enumerate(indices)],[]) 373 ML_coef_pos = self.pq.get_coef_position(ML_indices) 374 ML_sign_convention = ' ' if len(ML_indices)%2==0 else '-' 375 lines.append("c Coefficient %s"%coeff_str) 376 lines.append("GOLEM_COEFS%%c%d(%d,%d)=%sML_COEFS(%d)"\ 377 % (k, lab, i+1, ML_sign_convention, ML_coef_pos)) 378 379 subroutines.append('\n'.join(lines+['end'])) 380 381 return '\n\n'.join(subroutines) 382
383 - def write_wl_updater(self,r_1,r_2):
384 """ Give out the subroutine to update a polynomial of rank r_1 with 385 one of rank r_2 """ 386 387 # The update is basically given by 388 # OUT(j,coef,i) = A(k,*,i) x B(j,*,k) 389 # with k a summed index and the 'x' operation is equivalent to 390 # putting together two regular polynomial in q with scalar coefficients 391 # The complexity of this subroutine is therefore 392 # MAXLWFSIZE**3 * NCoef(r_1) * NCoef(r_2) 393 # Which is for example 22'400 when updating a rank 4 loop wavefunction 394 # with a rank 1 updater. 395 396 lines=[] 397 398 # Start by writing out the header: 399 lines.append( 400 """SUBROUTINE %(sub_prefix)sUPDATE_WL_%(r_1)d_%(r_2)d(A,LCUT_SIZE,B,IN_SIZE,OUT_SIZE,OUT) 401 include 'coef_specs.inc' 402 INTEGER I,J,K 403 %(coef_format)s A(MAXLWFSIZE,0:LOOP_MAXCOEFS-1,MAXLWFSIZE) 404 %(coef_format)s B(MAXLWFSIZE,0:VERTEXMAXCOEFS-1,MAXLWFSIZE) 405 %(coef_format)s OUT(MAXLWFSIZE,0:LOOP_MAXCOEFS-1,MAXLWFSIZE) 406 INTEGER LCUT_SIZE,IN_SIZE,OUT_SIZE 407 """%{'sub_prefix':self.sub_prefix,'r_1':r_1,'r_2':r_2, 408 'coef_format':self.coef_format}) 409 410 # Start the loop on the elements i,j of the vector OUT(i,coef,j) 411 lines.append("DO I=1,LCUT_SIZE") 412 lines.append(" DO J=1,OUT_SIZE") 413 lines.append(" DO K=0,%d"%(get_number_of_coefs_for_rank(r_2+r_1)-1)) 414 lines.append(" OUT(J,K,I)=%s"%self.czero) 415 lines.append(" ENDDO") 416 lines.append(" DO K=1,IN_SIZE") 417 418 # Now we write the lines defining the coefs of OUT(j,*,i) from those 419 # of A(k,*,i) and B(j,*,k) 420 # The dictionary below stores the position of the new coefficient 421 # derived as keys and the list of the buidling blocks expressing 422 # them as values 423 coef_expressions={} 424 for coef_a in range(0,get_number_of_coefs_for_rank(r_1)): 425 for coef_b in range(0,get_number_of_coefs_for_rank(r_2)): 426 ind_list=self.pq.get_coef_at_position(coef_a)+\ 427 self.pq.get_coef_at_position(coef_b) 428 new_term="A(K,%d,I)*B(J,%d,K)"%(coef_a,coef_b) 429 new_position=self.pq.get_coef_position(ind_list) 430 try: 431 coef_expressions[new_position].append(new_term) 432 except KeyError: 433 coef_expressions[new_position]=[new_term,] 434 for coef, value in coef_expressions.items(): 435 split=0 436 while split<len(value): 437 lines.append("OUT(J,%d,I)=OUT(J,%d,I)+"%(coef,coef)+\ 438 '+'.join(value[split:split+self.line_split])) 439 split=split+self.line_split 440 441 # And now we simply close the enddo. 442 lines.append(" ENDDO") 443 lines.append(" ENDDO") 444 lines.append("ENDDO") 445 lines.append("END") 446 447 # return the subroutine 448 return '\n'.join(lines)
449
450 - def write_polynomial_evaluator(self):
451 """ Give out the subroutine to evaluate a polynomial of a rank up to 452 the maximal one specified when initializing the FortranPolynomialRoutines 453 object. """ 454 lines=[] 455 456 # Start by writing out the header: 457 lines.append("""SUBROUTINE %(sub_prefix)sEVAL_POLY(C,R,Q,OUT) 458 include 'coef_specs.inc' 459 %(coef_format)s C(0:LOOP_MAXCOEFS-1) 460 INTEGER R 461 %(coef_format)s Q(0:3) 462 %(coef_format)s OUT 463 """%{'sub_prefix':self.sub_prefix, 464 'coef_format':self.coef_format}) 465 466 # Start by the trivial coefficient of order 0. 467 lines.append("OUT=C(0)") 468 # Now scan them all progressively 469 for r in range(1,self.max_rank+1): 470 lines.append("IF (R.GE.%d) then"%r) 471 terms=[] 472 for coef_num in range(get_number_of_coefs_for_rank(r-1) 473 ,get_number_of_coefs_for_rank(r)): 474 coef_inds=self.pq.get_coef_at_position(coef_num) 475 terms.append('*'.join(['C(%d)'%coef_num,]+ 476 ['Q(%d)'%ind for ind in coef_inds])) 477 split=0 478 while split<len(terms): 479 lines.append("OUT=OUT+"+\ 480 '+'.join(terms[split:split+self.line_split])) 481 split=split+self.line_split 482 lines.append("ENDIF") 483 lines.append("END") 484 485 return '\n'.join(lines)
486
487 - def write_wl_merger(self):
488 """ Give out the subroutine to merge the components of a final loop 489 wavefunction of a loop to create the coefficients of the polynomial 490 representing the numerator, while multiplying each of them by 'const'.""" 491 lines=[] 492 493 # Start by writing out the header: 494 lines.append("""SUBROUTINE %(sub_prefix)sMERGE_WL(WL,R,LCUT_SIZE,CONST,OUT) 495 include 'coef_specs.inc' 496 INTEGER I,J 497 %(coef_format)s WL(MAXLWFSIZE,0:LOOP_MAXCOEFS-1,MAXLWFSIZE) 498 INTEGER R,LCUT_SIZE 499 %(coef_format)s CONST 500 %(coef_format)s OUT(0:LOOP_MAXCOEFS-1) 501 """%{'sub_prefix':self.sub_prefix, 502 'coef_format':self.coef_format}) 503 504 # Add an array specifying how many coefs there are for given ranks 505 lines.append("""INTEGER NCOEF_R(0:%(max_rank)d) 506 DATA NCOEF_R/%(ranks)s/ 507 """%{'max_rank':self.max_rank,'ranks':','.join([ 508 str(get_number_of_coefs_for_rank(r)) for r in 509 range(0,self.max_rank+1)])}) 510 511 # Now scan them all progressively 512 lines.append("DO I=1,LCUT_SIZE") 513 lines.append(" DO J=0,NCOEF_R(R)-1") 514 lines.append(" OUT(J)=OUT(J)+WL(I,J,I)*CONST") 515 lines.append(" ENDDO") 516 lines.append("ENDDO") 517 lines.append("END") 518 519 return '\n'.join(lines)
520
521 - def write_add_coefs(self):
522 """ Give out the subroutine to simply add together the coefficients 523 of two loop polynomials of rank R1 and R2 storing the result in the 524 first polynomial given in the arguments.""" 525 lines=[] 526 527 # Start by writing out the header: 528 lines.append("""SUBROUTINE %(sub_prefix)sADD_COEFS(A,RA,B,RB) 529 include 'coef_specs.inc' 530 INTEGER I 531 %(coef_format)s A(0:LOOP_MAXCOEFS-1),B(0:LOOP_MAXCOEFS-1) 532 INTEGER RA,RB 533 """%{'sub_prefix':self.sub_prefix, 534 'coef_format':self.coef_format}) 535 536 # Add an array specifying how many coefs there are for given ranks 537 lines.append("""INTEGER NCOEF_R(0:%(max_rank)d) 538 DATA NCOEF_R/%(ranks)s/ 539 """%{'max_rank':self.max_rank,'ranks':','.join([ 540 str(get_number_of_coefs_for_rank(r)) for r in 541 range(0,self.max_rank+1)])}) 542 543 # Now scan them all progressively 544 lines.append("DO I=0,NCOEF_R(RB)-1") 545 lines.append(" A(I)=A(I)+B(I)") 546 lines.append("ENDDO") 547 lines.append("END") 548 549 return '\n'.join(lines)
550
551 -class FromIREGIFortranCodeGenerator():
552 """ Back up of the class Polynomial, which uses the same coefficeints orders with IREGI. 553 It is useful in the case that the order of MadLoop coefficients changes in the future.""" 554
555 - def __init__(self, rank):
556 557 assert rank > -1, "The rank of a q-polynomial should be 0 or positive" 558 self.rank=rank 559 self.init_coef_list()
560
561 - def init_coef_list(self):
562 """ Creates a list whose elements are arrays being the coefficient 563 indices sorted in growing order and the value is their position in a 564 one-dimensional vector. For example the position of the coefficient 565 C_01032 will be placed in the list under array.array('i',(0,0,1,3,2)). 566 """ 567 self.coef_list=[] 568 self.coef_list.append(array.array('i',())) 569 570 if self.rank==0: 571 return 572 573 tmp_coef_list=[array.array('i',(0,)),array.array('i',(1,)), 574 array.array('i',(2,)),array.array('i',(3,))] 575 self.coef_list.extend(tmp_coef_list) 576 577 for i in range(1,self.rank): 578 new_tmp_coef_list=[] 579 for coef in tmp_coef_list: 580 for val in range(coef[-1],4): 581 new_coef=copy.copy(coef) 582 new_coef.append(val) 583 new_tmp_coef_list.append(new_coef) 584 tmp_coef_list=new_tmp_coef_list 585 self.coef_list.extend(tmp_coef_list)
586
587 - def get_coef_position(self, indices_list):
588 """ Returns the canonical position for a coefficient characterized 589 by the value of the indices of the loop momentum q it multiplies, 590 that is for example C_01032 multiplying q_0*q_1*q_0*q_3*q_2 """ 591 592 new_indices_list=copy.copy(indices_list) 593 new_indices_list.sort() 594 try: 595 return self.coef_list.index(array.array('i',new_indices_list)) 596 except ValueError: 597 raise PolynomialError,\ 598 "The index %s looked for could not be found"%str(indices_list)
599
600 - def get_coef_at_position(self, pos):
601 """ Returns the coefficient at position pos in the one dimensional 602 vector """ 603 return list(self.coef_list[pos])
604
605 606 -class FromGolem95FortranCodeGenerator():
607 """ Just a container class with helper functions taken from the script 608 tens.py of golem which generates most of the golem95 tens_rec.f fortran 609 code.""" 610 611 PRIMES = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 612 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 613 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 614 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 615 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 616 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 617 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 618 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 619 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 620 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 621 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 622 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 623 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 624 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 625 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 626 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 627 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013, 628 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 629 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 630 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, 631 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, 632 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373] 633 634 @classmethod
635 - def combinat(cls, n, k):
636 """ 637 Calculates the binomial coefficient (n atop k). 638 """ 639 if k < 0 or k > n: 640 return 0 641 else: 642 num = 1 643 den = 1 644 for i in range(1, k+1): 645 num *= n-i+1 646 den *= i 647 return num/den
648 649 @classmethod
650 - def generate_mapping(cls, R, k):
651 """ 652 Generates a mapping from tensor components \hat{C}(a_1, ..., a_k) 653 into a one dimensional array. 654 655 PARAMETER 656 657 R -- rank 658 k -- number of non-zero components of q 659 660 RETURN 661 662 (lst, dic) 663 664 lst -- list of (a_1, ..., a_k) 665 dic -- mapping from (a_1, ..., a_k) -> int 666 667 lst[dic[X]] = X if X in dic 668 """ 669 670 def rec_generator(k, R): 671 if k == 0: 672 yield [] 673 elif k <= R: 674 for a_1 in range(1, R - (k - 1) + 1): 675 if k > 1: 676 for tail in rec_generator(k - 1, R - a_1): 677 yield [a_1] + tail 678 else: 679 yield [a_1]
680 681 lst = [] 682 dic = {} 683 i = 0 684 for indices in rec_generator(k, R): 685 t = tuple(indices) 686 lst.append(t) 687 dic[t] = i 688 i += 1 689 690 assert i == cls.combinat(R, k), \ 691 "len(%s) != %d, R=%d,k=%d" % (lst,cls.combinat(R, k),R,k) 692 return lst, dic
693 694 @classmethod
695 - def generate_equations(cls, R, k):
696 """ 697 Generates a set of equations for a given number of non-zero 698 components and fixed maximum rank. 699 700 PARAMETER 701 702 R -- rank 703 k -- number of non-zero components of q 704 705 RETURN 706 707 (LHS, RHS) 708 709 LHS -- a matrix (i.e. list of lists) of coefficients 710 RHS -- a list of values of q 711 """ 712 713 lst, dic = cls.generate_mapping(R, k) 714 l = len(lst) 715 LHS = [] 716 RHS = [] 717 for num_eq in range(l): 718 q = map(lambda i: cls.PRIMES[i], lst[num_eq]) 719 coeffs = [ 720 reduce(lambda x,y: x*y, map(lambda (b,e): b**e, zip(q, term)), 1) 721 for term in lst] 722 LHS.append(coeffs) 723 RHS.append(q) 724 725 return LHS, RHS, lst, dic
726 727 @classmethod
728 - def select(cls, items, k):
729 """ 730 Iterator over all selections of k elements from a given list. 731 732 PARAMETER 733 734 items -- list of elements to choose from (no repetitions) 735 k -- number of elements to select. 736 """ 737 n = len(items) 738 # We use the fact that 739 # (n choose k) = (1 choose 1)(n-1 choose k-1)+(1 choose 0)(n-1 choose k) 740 if k == n: 741 yield items[:] 742 elif k == 0: 743 yield [] 744 elif 0 < k and k < n: 745 head = items[0:1] 746 tail = items[1:] 747 for result in cls.select(tail, k-1): 748 yield head + result 749 for result in cls.select(tail, k): 750 yield result
751 752 if __name__ == '__main__': 753 """I test here the write_golem95_mapping function""" 754 755 max_rank=6 756 FPR=FortranPolynomialRoutines(max_rank) 757 print "Output of write_golem95_mapping function for max_rank=%d:\n\n"%max_rank 758 759 import os 760 import sys 761 root_path = os.path.split(os.path.dirname(os.path.realpath( __file__ )))[0] 762 sys.path.insert(0, os.path.join(root_path,os.path.pardir)) 763 import madgraph.iolibs.file_writers as writers 764 FWriter = writers.FortranWriter("GOLEM95_interface.f") 765 FWriter.writelines(FPR.write_golem95_mapping()) 766