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