├── README.md ├── LICENSE ├── particle.py ├── .gitignore ├── qcd.py ├── durham.py ├── vector.py ├── histogram.py ├── uterms.py ├── .shower.py ├── .matrix.py ├── matrix.py ├── algorithm1.py ├── algorithm1_stefan.py └── flatmc.py /README.md: -------------------------------------------------------------------------------- 1 | # flatmc -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Holger Schulz 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /particle.py: -------------------------------------------------------------------------------- 1 | 2 | import math as m 3 | 4 | from vector import Vec4 5 | 6 | class Particle: 7 | 8 | def __init__(self,pdgid,momentum,col=[0,0]): 9 | self.Set(pdgid,momentum,col) 10 | 11 | def __repr__(self): 12 | return "{0} {1} {2}".format(self.pid,self.mom,self.col) 13 | 14 | def __str__(self): 15 | return "{0} {1} {2}".format(self.pid,self.mom,self.col) 16 | 17 | def Set(self,pdgid,momentum,col=[0,0]): 18 | self.pid = pdgid 19 | self.mom = momentum 20 | self.col = col 21 | 22 | def ColorConnected(self,p): 23 | return (self.col[0] > 0 and self.col[0] == p.col[1]) or \ 24 | (self.col[1] > 0 and self.col[1] == p.col[0]) 25 | 26 | def CheckEvent(event): 27 | psum = Vec4() 28 | csum = {} 29 | for p in event: 30 | psum += p.mom 31 | if p.col[0] > 0: 32 | csum[p.col[0]] = csum.get(p.col[0],0) + 1 33 | if csum[p.col[0]] == 0: del csum[p.col[0]] 34 | if p.col[1] > 0: 35 | csum[p.col[1]] = csum.get(p.col[1],0) - 1 36 | if csum[p.col[1]] == 0: del csum[p.col[1]] 37 | return (m.fabs(psum.E)<1.e-12 and \ 38 | m.fabs(psum.px)<1.e-12 and \ 39 | m.fabs(psum.py)<1.e-12 and \ 40 | m.fabs(psum.pz)<1.e-12 and \ 41 | len(csum) == 0) 42 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | MANIFEST 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | .pytest_cache/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | local_settings.py 57 | db.sqlite3 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # Sphinx documentation 67 | docs/_build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | # Jupyter Notebook 73 | .ipynb_checkpoints 74 | 75 | # pyenv 76 | .python-version 77 | 78 | # celery beat schedule file 79 | celerybeat-schedule 80 | 81 | # SageMath parsed files 82 | *.sage.py 83 | 84 | # Environments 85 | .env 86 | .venv 87 | env/ 88 | venv/ 89 | ENV/ 90 | env.bak/ 91 | venv.bak/ 92 | 93 | # Spyder project settings 94 | .spyderproject 95 | .spyproject 96 | 97 | # Rope project settings 98 | .ropeproject 99 | 100 | # mkdocs documentation 101 | /site 102 | 103 | # mypy 104 | .mypy_cache/ 105 | -------------------------------------------------------------------------------- /qcd.py: -------------------------------------------------------------------------------- 1 | 2 | import math as m 3 | 4 | NC = 3. 5 | TR = 1./2. 6 | CA = NC 7 | CF = (NC*NC-1.)/(2.*NC) 8 | 9 | class AlphaS: 10 | 11 | def __init__(self,mz,asmz,order=1,mb=4.75,mc=1.3): 12 | self.order = order 13 | self.mc2 = mc*mc 14 | self.mb2 = mb*mb 15 | self.mz2 = mz*mz 16 | self.asmz = asmz 17 | self.asmb = self(self.mb2) 18 | self.asmc = self(self.mc2) 19 | print ("\\alpha_s({0}) = {1}".format(mz,self(self.mz2))) 20 | 21 | def beta0(self,nf): 22 | return 11./6.*CA-2./3.*TR*nf 23 | 24 | def beta1(self,nf): 25 | return 17./6.*CA*CA-(5./3.*CA+CF)*TR*nf 26 | 27 | def as0(self,t): 28 | if t >= self.mb2: 29 | tref = self.mz2 30 | asref = self.asmz 31 | b0 = self.beta0(5)/(2.*m.pi) 32 | elif t >= self.mc2: 33 | tref = self.mb2 34 | asref = self.asmb 35 | b0 = self.beta0(4)/(2.*m.pi) 36 | else: 37 | tref = self.mc2 38 | asref = self.asmc 39 | b0 = self.beta0(3)/(2.*m.pi) 40 | return 1./(1./asref+b0*m.log(t/tref)) 41 | 42 | def as1(self,t): 43 | if t >= self.mb2: 44 | tref = self.mz2 45 | asref = self.asmz 46 | b0 = self.beta0(5)/(2.*m.pi) 47 | b1 = self.beta1(5)/pow(2.*m.pi,2) 48 | elif t >= self.mc2: 49 | tref = self.mb2 50 | asref = self.asmb 51 | b0 = self.beta0(4)/(2.*m.pi) 52 | b1 = self.beta1(4)/pow(2.*m.pi,2) 53 | else: 54 | tref = self.mc2 55 | asref = self.asmc 56 | b0 = self.beta0(3)/(2.*m.pi) 57 | b1 = self.beta1(3)/pow(2.*m.pi,2) 58 | w = 1.+b0*asref*m.log(t/tref) 59 | return asref/w*(1.-b1/b0*asref*m.log(w)/w) 60 | 61 | def __call__(self,t): 62 | if self.order == 0: return self.as0(t) 63 | return self.as1(t) 64 | -------------------------------------------------------------------------------- /durham.py: -------------------------------------------------------------------------------- 1 | 2 | import math as m 3 | 4 | from vector import Vec4 5 | from particle import Particle 6 | 7 | class Algorithm: 8 | 9 | def Yij(self,p,q): 10 | pq = p.px*q.px+p.py*q.py+p.pz*q.pz 11 | return 2.*pow(min(p.E,q.E),2)*(1.0-min(max(pq/m.sqrt(p.P2()*q.P2()),-1.0),1.0))/self.ecm2 12 | 13 | def Cluster(self,event): 14 | self.ecm2 = (event[0].mom+event[1].mom).M2() 15 | p = [ i.mom for i in event[2:] ] 16 | kt2 = [] 17 | n = len(p) 18 | imap = list(range(n)) 19 | kt2ij = [ [ 0 for i in range(n) ] for j in range(n) ] 20 | dmin = 1 21 | for i in range(n): 22 | for j in range(i): 23 | dij = kt2ij[i][j] = self.Yij(p[i],p[j]) 24 | if dij < dmin: dmin = dij; ii = i; jj = j 25 | while n>2: 26 | n -= 1 27 | kt2.append(dmin); 28 | jjx = imap[jj] 29 | p[jjx] += p[imap[ii]] 30 | for i in range(ii,n): imap[i] = imap[i+1] 31 | for j in range(jj): kt2ij[jjx][imap[j]] = self.Yij(p[jjx],p[imap[j]]) 32 | for i in range(jj+1,n): kt2ij[imap[i]][jjx] = self.Yij(p[jjx],p[imap[i]]) 33 | dmin = 1 34 | for i in range(n): 35 | for j in range(i): 36 | dij = kt2ij[imap[i]][imap[j]] 37 | if dij < dmin: dmin = dij; ii = i; jj = j 38 | return kt2 39 | 40 | from histogram import Histo1D 41 | 42 | class Analysis: 43 | 44 | def __init__(self,n=1): 45 | self.n = 0. 46 | self.ynm = [[ Histo1D(100,-4.3,-0.3,'/LL_JetRates/log10_y_{0}{1}\n'.format(i+2,i+3)) 47 | for i in range(4) ] for i in range(n+1) ] 48 | self.duralg = Algorithm() 49 | 50 | def Analyze(self,event,w,weights=[]): 51 | self.n += 1. 52 | kt2 = self.duralg.Cluster(event) 53 | for j in range(len(self.ynm[0])): 54 | self.ynm[0][j].Fill(m.log10(kt2[-1-j]) if len(kt2)>j else -5.,w) 55 | for i in range(len(weights)): 56 | self.ynm[i+1][j].Fill(m.log10(kt2[-1-j]) if len(kt2)>j else -5.,w*weights[i]) 57 | 58 | def Finalize(self,name): 59 | for h in self.ynm[0]: h.ScaleW(1./self.n) 60 | file = open(name+".yoda","w") 61 | file.write("\n\n".join([ str(h) for h in self.ynm[0] ])) 62 | file.close() 63 | for i in range(1,len(self.ynm)): 64 | for h in self.ynm[i]: h.ScaleW(1./self.n) 65 | file = open(name+".{0}.yoda".format(i),"w") 66 | file.write("\n\n".join([ str(h) for h in self.ynm[i] ])) 67 | file.close() 68 | -------------------------------------------------------------------------------- /vector.py: -------------------------------------------------------------------------------- 1 | 2 | import math as m 3 | 4 | class Vec4: 5 | 6 | def __init__(self,E=0,px=0,py=0,pz=0): 7 | self.E = E 8 | self.px = px 9 | self.py = py 10 | self.pz = pz 11 | 12 | def __getitem__(self,i): 13 | if i == 0: return self.E 14 | if i == 1: return self.px 15 | if i == 2: return self.py 16 | if i == 3: return self.pz 17 | raise Exception('Vec4D') 18 | 19 | def __repr__(self): 20 | return '({0},{1},{2},{3})'.format(self.E,self.px,self.py,self.pz) 21 | 22 | def __str__(self): 23 | return '({0},{1},{2},{3})'.format(self.E,self.px,self.py,self.pz) 24 | 25 | def __add__(self,v): 26 | return Vec4(self.E+v.E,self.px+v.px,self.py+v.py,self.pz+v.pz) 27 | 28 | def __sub__(self,v): 29 | return Vec4(self.E-v.E,self.px-v.px,self.py-v.py,self.pz-v.pz) 30 | 31 | def __neg__(self): 32 | return Vec4(-self.E,-self.px,-self.py,-self.pz) 33 | 34 | def __mul__(self,v): 35 | if isinstance(v,Vec4): 36 | return self.E*v.E-self.px*v.px-self.py*v.py-self.pz*v.pz 37 | return Vec4(self.E*v,self.px*v,self.py*v,self.pz*v) 38 | 39 | def __rmul__(self,v): 40 | if isinstance(v,Vec4): 41 | return self.E*v.E-self.px*v.px-self.py*v.py-self.pz*v.pz 42 | return Vec4(self.E*v,self.px*v,self.py*v,self.pz*v) 43 | 44 | def __truediv__(self,v): 45 | return Vec4(self.E/v,self.px/v,self.py/v,self.pz/v) 46 | 47 | def M2(self): 48 | return self*self 49 | 50 | def M(self): 51 | return m.sqrt(self.M2()) 52 | 53 | def P2(self): 54 | return self.px*self.px+self.py*self.py+self.pz*self.pz 55 | 56 | def P(self): 57 | return m.sqrt(self.P2()) 58 | 59 | def PT2(self): 60 | return self.px*self.px+self.py*self.py 61 | 62 | def PT(self): 63 | return m.sqrt(self.PT2()) 64 | 65 | def Theta(self) : 66 | return m.acos(self.pz/self.P()) 67 | 68 | def Phi(self) : 69 | if self.px==0 and self.py==0: 70 | return 0.0 71 | else: 72 | return m.atan2(self.py,self.px) 73 | 74 | def Cross(self,v): 75 | return Vec4(0.0, 76 | self.py*v.pz-self.pz*v.py, 77 | self.pz*v.px-self.px*v.pz, 78 | self.px*v.py-self.py*v.px) 79 | 80 | def Boost(self,v): 81 | rsq = self.M() 82 | v0 = (self.E*v.E-self.px*v.px-self.py*v.py-self.pz*v.pz)/rsq; 83 | c1 = (v.E+v0)/(rsq+self.E) 84 | return Vec4(v0, 85 | v.px-c1*self.px, 86 | v.py-c1*self.py, 87 | v.pz-c1*self.pz) 88 | 89 | def BoostBack(self,v): 90 | rsq = self.M() 91 | v0 = (self.E*v.E+self.px*v.px+self.py*v.py+self.pz*v.pz)/rsq; 92 | c1 = (v.E+v0)/(rsq+self.E) 93 | return Vec4(v0, 94 | v.px+c1*self.px, 95 | v.py+c1*self.py, 96 | v.pz+c1*self.pz) 97 | -------------------------------------------------------------------------------- /histogram.py: -------------------------------------------------------------------------------- 1 | 2 | import sys 3 | 4 | class Bin1D: 5 | 6 | def __init__(self,xmin,xmax): 7 | self.xmin = xmin 8 | self.xmax = xmax 9 | self.w = 0. 10 | self.w2 = 0. 11 | self.wx = 0. 12 | self.wx2 = 0. 13 | self.n = 0. 14 | 15 | def __repr__(self): 16 | return str(self) 17 | 18 | def __str__(self): 19 | return "{0:10.6e}\t{1:10.6e}\t{2:10.6e}\t{3:10.6e}\t{4:10.6e}\t{5:10.6e}\t{6}".format\ 20 | (self.xmin,self.xmax,self.w,self.w2,self.wx,self.wx2,int(self.n)) 21 | 22 | def Format(self,tag): 23 | return "{0}\t{0}\t{1:10.6e}\t{2:10.6e}\t{3:10.6e}\t{4:10.6e}\t{5}".format\ 24 | (tag,self.w,self.w2,self.wx,self.wx2,int(self.n)) 25 | 26 | def Fill(self,x,w): 27 | self.w += w 28 | self.w2 += w*w 29 | self.wx += w*x 30 | self.wx2 += w*w*x 31 | self.n += 1. 32 | 33 | def ScaleW(self,scale): 34 | self.w *= scale 35 | self.w2 *= scale*scale 36 | self.wx *= scale 37 | self.wx2 *= scale*scale 38 | 39 | class Histo1D: 40 | 41 | def __init__(self,nbin,xmin,xmax,name): 42 | self.name = name 43 | self.bins = [] 44 | self.uflow = Bin1D(-sys.float_info.max,xmin) 45 | width = (xmax-xmin)/nbin 46 | for i in range(nbin): 47 | self.bins.append(Bin1D(xmin+i*width,xmin+(i+1)*width)) 48 | self.oflow = Bin1D(xmax,sys.float_info.max) 49 | self.total = Bin1D(-sys.float_info.max,sys.float_info.max) 50 | self.scale = 1. 51 | 52 | def __repr__(self): 53 | return str(self) 54 | 55 | def __str__(self): 56 | s = "BEGIN YODA_HISTO1D {0}\n\n".format(self.name) 57 | s += "Path={0}\n\n".format(self.name) 58 | s += "ScaledBy={0}\n".format(self.scale) 59 | s += "Title=\nType=Histo1D\n" 60 | s += "# ID\tID\tsumw\tsumw2\tsumwx\tsumwx2\tnumEntries\n" 61 | s += self.total.Format("Total")+"\n" 62 | s += self.uflow.Format("Underflow")+"\n" 63 | s += self.oflow.Format("Overflow")+"\n" 64 | s += "# xlow\txhigh\tsumw\tsumw2\tsumwx\tsumwx2\tnumEntries\n" 65 | for i in range(len(self.bins)): 66 | s += "{0}\n".format(self.bins[i]) 67 | s += "END YODA_HISTO1D\n" 68 | return s 69 | 70 | def Fill(self,x,w): 71 | l = 0 72 | r = len(self.bins)-1 73 | c = int((l+r)/2) 74 | a = self.bins[c].xmin 75 | while r-l > 1: 76 | if x < a: r = c 77 | else: l = c 78 | c = int((l+r)/2) 79 | a = self.bins[c].xmin 80 | if x > self.bins[r].xmin: 81 | self.oflow.Fill(x,w) 82 | elif x < self.bins[l].xmin: 83 | self.uflow.Fill(x,w) 84 | else: 85 | self.bins[l].Fill(x,w) 86 | self.total.Fill(x,w) 87 | 88 | def ScaleW(self,scale): 89 | self.total.ScaleW(scale) 90 | self.uflow.ScaleW(scale) 91 | self.oflow.ScaleW(scale) 92 | for i in range(len(self.bins)): 93 | self.bins[i].ScaleW(scale) 94 | self.scale = scale 95 | 96 | 97 | -------------------------------------------------------------------------------- /uterms.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import numpy as np 4 | 5 | def getEqns(N): 6 | """ 7 | String representations of equations to solve for N external particles. 8 | """ 9 | 10 | for i in reversed(range(2, N)): 11 | print("r_{} = {}u^{} - {}u^{}".format(i-1, N-i+1, N-i, N-i, N-i+1)) 12 | 13 | 14 | def mkData(N, npoint=100): 15 | U=np.linspace(0,1,npoint) 16 | ret = [] 17 | for i in reversed(range(2, N)): 18 | ret.append( (N-i+1)*U**(N-i) - (N-i)*U**(N-i+1)) 19 | return U, ret 20 | 21 | 22 | 23 | if __name__ == "__main__": 24 | import sys 25 | 26 | NP = int(sys.argv[1]) 27 | getEqns(NP) 28 | import matplotlib.pyplot as plt 29 | plt.style.use("ggplot") 30 | 31 | # U, YY = mkData(NP) 32 | 33 | # for num, y in enumerate(YY): 34 | # plt.plot(U, y, label="$r_{}$".format(num+1)) 35 | # plt.legend() 36 | # plt.show() 37 | 38 | def u2(r1): 39 | """ 40 | Integration variable in the n=3 case 41 | """ 42 | return 1. - np.sqrt(1.-r1) 43 | 44 | def u3(r): 45 | kappa = np.cbrt( 2*np.sqrt(r*(r-1) ) -2*r +1 ) 46 | return 0.5*(kappa + 1./kappa + 1) 47 | 48 | def f(x, a, r): 49 | return a*x**(a-1) - (a-1)*x**a - r 50 | 51 | def fp(x, a): 52 | return a*(a-1)*(x**(a-2) - x**(a-1)) 53 | 54 | def fpp(x, a): 55 | return a*(a-1)*((a-2)*x**(a-3) - (a-1)*x**(a-2)) 56 | 57 | a=NP-1 58 | 59 | 60 | 61 | r = np.random.rand() 62 | print("Drawn random number r={}".format(r)) 63 | 64 | from scipy import optimize 65 | if a>2: 66 | res = optimize.newton(lambda x : f(x,a,r), r, fprime=lambda x: fp(x,a), fprime2=lambda x: fpp(x,a)) 67 | else: 68 | res = optimize.newton(lambda x : f(x,a,r), r, fprime=lambda x: fp(x,a)) 69 | 70 | # from IPython import embed 71 | # embed() 72 | 73 | # X = np.linspace(0,1,100) 74 | # plt.plot(X, f(X,a,r), label="f, r={}".format(r)) 75 | # plt.plot(X, fp(X,a), label="fp") 76 | # if a>2: 77 | # plt.plot(X, fpp(X,a), label="fpp") 78 | # plt.axvline(res, label="u={}".format(res)) 79 | # plt.legend() 80 | # plt.show() 81 | 82 | # Numerical experimentation --- measure distance between r and u 83 | NSAMPLES=int(sys.argv[2])#10000 84 | 85 | import time 86 | U = np.empty(NSAMPLES) 87 | R = np.empty(NSAMPLES) 88 | t1=time.time() 89 | # U = [optimize.newton(lambda x : f(x,a,r), r, fprime=lambda x: fp(x,a), fprime2=lambda x: fpp(x,a)) for r in R] 90 | # for num, r in enumerate(R): 91 | for num in range(NSAMPLES): 92 | r = np.random.rand() 93 | u = optimize.newton(lambda x : f(x,a,r), r, fprime=lambda x: fp(x,a), fprime2=lambda x: fpp(x,a)) 94 | R[num] = r 95 | U[num] = u 96 | 97 | t2=time.time() 98 | 99 | print("Evaluation of {} samples with a={} took {} seconds, residual = {}".format(NSAMPLES, a, t2-t1, sum([f(u,a,r) for u, r in zip(U,R)]))) 100 | 101 | 102 | print("Distance between u and r = {} +/- {}".format(np.mean(R-U), np.std(R-U))) 103 | 104 | plt.scatter(R,U, s=0.01) 105 | plt.show() 106 | 107 | # plt.hist(U, bins=50, label="u", histtype="step") 108 | # plt.hist(R, bins=50, label="r", histtype="step") 109 | # plt.legend() 110 | # plt.show() 111 | 112 | t1=time.time() 113 | UNO = [u2(r) for r in R] 114 | t2=time.time() 115 | print("Evaluation of {} samples with a={} took {} seconds".format(NSAMPLES, a, t2-t1)) 116 | # from IPython import embed 117 | # embed() 118 | 119 | -------------------------------------------------------------------------------- /.shower.py: -------------------------------------------------------------------------------- 1 | import math as m 2 | import random as r 3 | 4 | from vector import Vec4 5 | from particle import Particle, CheckEvent 6 | from qcd import AlphaS, NC, TR, CA, CF 7 | 8 | class Kernel: 9 | 10 | def __init__(self,flavs): 11 | self.flavs = flavs 12 | 13 | class Pqq (Kernel): 14 | 15 | def Value(self,z,y): 16 | return CF*(2./(1.-z*(1.-y))-(1.+z)) 17 | 18 | def Estimate(self,z): 19 | return CF*2./(1.-z) 20 | 21 | def Integral(self,zm,zp): 22 | return CF*2.*m.log((1.-zm)/(1.-zp)) 23 | 24 | def GenerateZ(self,zm,zp): 25 | return 1.+(zp-1.)*m.pow((1.-zm)/(1.-zp),r.random()) 26 | 27 | class Pgg (Kernel): 28 | 29 | def Value(self,z,y): 30 | return CA/2.*(2./(1.-z*(1.-y))-2.+z*(1.-z)) 31 | 32 | def Estimate(self,z): 33 | return CA/(1.-z) 34 | 35 | def Integral(self,zm,zp): 36 | return CA*m.log((1.-zm)/(1.-zp)) 37 | 38 | def GenerateZ(self,zm,zp): 39 | return 1.+(zp-1.)*m.pow((1.-zm)/(1.-zp),r.random()) 40 | 41 | class Pgq (Kernel): 42 | 43 | def Value(self,z,y): 44 | return TR/2.*(1.-2.*z*(1.-z)) 45 | 46 | def Estimate(self,z): 47 | return TR/2. 48 | 49 | def Integral(self,zm,zp): 50 | return TR/2.*(zp-zm) 51 | 52 | def GenerateZ(self,zm,zp): 53 | return zm+(zp-zm)*r.random() 54 | 55 | class Shower: 56 | 57 | def __init__(self,alpha,t0): 58 | self.t0 = t0 59 | self.alpha = alpha 60 | self.alphamax = alpha(self.t0) 61 | self.kernels = [ Pqq([fl,fl,21]) for fl in [-5,-4,-3,-2,-1,1,2,3,4,5] ] 62 | self.kernels += [ Pgq([21,fl,-fl]) for fl in [1,2,3,4,5] ] 63 | self.kernels += [ Pgg([21,21,21]) ] 64 | 65 | def MakeKinematics(self,z,y,phi,pijt,pkt): 66 | Q = pijt+pkt 67 | rkt = m.sqrt(Q.M2()*y*z*(1.-z)) 68 | kt1 = pijt.Cross(pkt) 69 | if kt1.P() < 1.e-6: kt1 = pijt.Cross(Vec4(0.,1.,0.,0.)) 70 | kt1 *= rkt*m.cos(phi)/kt1.P() 71 | kt2cms = Q.Boost(pijt).Cross(kt1) 72 | kt2cms *= rkt*m.sin(phi)/kt2cms.P() 73 | kt2 = Q.BoostBack(kt2cms) 74 | pi = z*pijt + (1.-z)*y*pkt + kt1 + kt2 75 | pj = (1.-z)*pijt + z*y*pkt - kt1 - kt2 76 | pk = (1.-y)*pkt 77 | return [pi,pj,pk] 78 | 79 | def MakeColors(self,flavs,colij,colk): 80 | self.c += 1 81 | if flavs[0] != 21: 82 | if flavs[0] > 0: 83 | return [ [self.c,0], [colij[0],self.c] ] 84 | else: 85 | return [ [0,self.c], [self.c,colij[1]] ] 86 | else: 87 | if flavs[1] == 21: 88 | if colij[0] == colk[1]: 89 | if colij[1] == colk[0] and r.random()>0.5: 90 | return [ [colij[0],self.c], [self.c,colij[1]] ] 91 | return [ [self.c,colij[1]], [colij[0],self.c] ] 92 | else: 93 | return [ [colij[0],self.c], [self.c,colij[1]] ] 94 | else: 95 | if flavs[1] > 0: 96 | return [ [colij[0],0], [0,colij[1]] ] 97 | else: 98 | return [ [0,colij[1]], [colij[0],0] ] 99 | 100 | def GeneratePoint(self,event): 101 | while self.t > self.t0: 102 | t = self.t0 103 | for split in event[2:]: 104 | for spect in event[2:]: 105 | if spect == split: continue 106 | if not split.ColorConnected(spect): continue 107 | for sf in self.kernels: 108 | if sf.flavs[0] != split.pid: continue 109 | m2 = (split.mom+spect.mom).M2() 110 | if m2 < 4.*self.t0: continue 111 | zp = .5*(1.+m.sqrt(1.-4.*self.t0/m2)) 112 | g = self.alphamax/(2.*m.pi)*sf.Integral(1.-zp,zp) 113 | tt = self.t*m.pow(r.random(),1./g) 114 | if tt > t: 115 | t = tt 116 | s = [ split, spect, sf, m2, zp ] 117 | self.t = t 118 | if t > self.t0: 119 | z = s[2].GenerateZ(1.-s[4],s[4]) 120 | y = t/s[3]/z/(1.-z) 121 | if y < 1.: 122 | f = (1.-y)*self.alpha(t)*s[2].Value(z,y) 123 | g = self.alphamax*s[2].Estimate(z) 124 | if f/g > r.random(): 125 | phi = 2.*m.pi*r.random() 126 | moms = self.MakeKinematics(z,y,phi,s[0].mom,s[1].mom) 127 | cols = self.MakeColors(s[2].flavs,s[0].col,s[1].col) 128 | event.append(Particle(s[2].flavs[2],moms[1],cols[1])) 129 | s[0].Set(s[2].flavs[1],moms[0],cols[0]) 130 | s[1].mom = moms[2] 131 | return 132 | 133 | def Run(self,event,t): 134 | self.c = 1 135 | self.t = t 136 | while self.t > self.t0: 137 | self.GeneratePoint(event) 138 | 139 | # build and run the generator 140 | 141 | import sys 142 | from matrix import eetojj 143 | from durham import Analysis 144 | 145 | alphas = AlphaS(91.1876,0.118) 146 | hardxs = eetojj(alphas) 147 | shower = Shower(alphas,t0=1.) 148 | jetrat = Analysis() 149 | 150 | r.seed(123456) 151 | for i in range(100000): 152 | event, weight = hardxs.GenerateLOPoint() 153 | t = (event[0].mom+event[1].mom).M2() 154 | shower.Run(event,t) 155 | sys.stdout.write('\rEvent {0}'.format(i)) 156 | sys.stdout.flush() 157 | jetrat.Analyze(event,weight) 158 | jetrat.Finalize("myshower") 159 | print "" 160 | -------------------------------------------------------------------------------- /.matrix.py: -------------------------------------------------------------------------------- 1 | 2 | import math as m 3 | import random as r 4 | 5 | from vector import Vec4 6 | from particle import Particle 7 | 8 | class eetojj: 9 | 10 | def __init__(self,alphas,ecms=91.2): 11 | self.alphas = alphas 12 | self.ecms = ecms 13 | self.MZ2 = pow(91.1876,2.) 14 | self.GZ2 = pow(2.4952,2.) 15 | self.alpha = 1./128.802 16 | self.sin2tw = 0.22293 17 | self.amin = 1.e-10 18 | self.ye = .5 19 | self.ze = .01 20 | self.ws = .25 21 | 22 | def ME2(self,fl,s,t): 23 | qe = -1. 24 | ae = -0.5 25 | ve = ae - 2.*qe*self.sin2tw; 26 | qf = 2./3. if fl in [2,4] else -1./3. 27 | af = 0.5 if fl in [2,4] else -0.5 28 | vf = af - 2.*qf*self.sin2tw; 29 | kappa = 1./(4.*self.sin2tw*(1.-self.sin2tw)) 30 | chi1 = kappa * s * (s-self.MZ2)/(pow(s-self.MZ2,2.) + self.GZ2*self.MZ2); 31 | chi2 = pow(kappa * s,2.)/(pow(s-self.MZ2,2.) + self.GZ2*self.MZ2); 32 | term1 = (1+pow(1.+2.*t/s,2.))*(pow(qf*qe,2.)+2.*(qf*qe*vf*ve)*chi1+(ae*ae+ve*ve)*(af*af+vf*vf)*chi2) 33 | term2 = (1.+2.*t/s)*(4.*qe*qf*ae*af*chi1+8.*ae*ve*af*vf*chi2) 34 | return pow(4.*m.pi*self.alpha,2.)*3.*(term1+term2) 35 | 36 | def GeneratePoint(self): 37 | ct = 2.*r.random()-1. 38 | st = m.sqrt(1.-ct*ct) 39 | phi = 2.*m.pi*r.random() 40 | p1 = Vec4(1,st*m.cos(phi),st*m.sin(phi),ct)*self.ecms/2. 41 | p2 = Vec4(p1.E,-p1.px,-p1.py,-p1.pz) 42 | pa = Vec4(self.ecms/2,0,0,self.ecms/2.) 43 | pb = Vec4(self.ecms/2,0,0,-self.ecms/2.) 44 | fl = r.randint(1,5) 45 | lome = self.ME2(fl,(pa+pb).M2(),(pa-p1).M2()) 46 | dxs = 5.*lome*3.89379656e8/(8.*m.pi)/(2.*pow(self.ecms,2)) 47 | return ( [ 48 | Particle(-11,-pa), 49 | Particle(11,-pb), 50 | Particle(fl,p1,[1,0]), 51 | Particle(-fl,p2,[0,1]) 52 | ], dxs, lome ) 53 | 54 | def GenerateLOPoint(self): 55 | lo = self.GeneratePoint() 56 | return ( lo[0], lo[1] ) 57 | 58 | def GeneratePOWHEGPoint(self): 59 | lo = self.GeneratePoint() 60 | mu = self.ecms 61 | l = m.log(mu*mu/(lo[0][2].mom+lo[0][3].mom).M2()) 62 | V = [ -2., -3. - 2.*l, -8.+m.pi*m.pi - 3.*l - l*l ] 63 | I = [ 2., 3. + 2.*l, 19./2.-m.pi*m.pi + 3.*l + l*l ] 64 | if V[0]+I[0] != 0.: 65 | print "Pole check failed (double pole)" 66 | if V[1]+I[1] != 0.: 67 | print "Pole check failed (single pole)" 68 | K = self.alphas(mu*mu)/(2.*m.pi)*4./3.*(V[2]+I[2]) 69 | return ( lo[0], lo[1]*(1.+K) ) 70 | 71 | def MakeKinematics(self,z,y,phi,pijt,pkt): 72 | Q = pijt+pkt 73 | rkt = m.sqrt(Q.M2()*y*z*(1.-z)) 74 | kt1 = pijt.Cross(pkt) 75 | if kt1.P() < 1.e-6: kt1 = pijt.Cross(Vec4(0.,1.,0.,0.)) 76 | kt1 *= rkt*m.cos(phi)/kt1.P() 77 | kt2cms = Q.Boost(pijt).Cross(kt1) 78 | kt2cms *= rkt*m.sin(phi)/kt2cms.P() 79 | kt2 = Q.BoostBack(kt2cms) 80 | pi = z*pijt + (1.-z)*y*pkt + kt1 + kt2 81 | pj = (1.-z)*pijt + z*y*pkt - kt1 - kt2 82 | pk = (1.-y)*pkt 83 | return [pi,pj,pk] 84 | 85 | def Real(self,lome,p1,p2,p3,mu): 86 | s12 = 2.*p1*p2 87 | s13 = 2.*p1*p3 88 | s23 = 2.*p2*p3 89 | R = lome*(s23/s13+s13/s23+2.*s12*(s12+s13+s23)/(s13*s23)) 90 | cpl = 8.*m.pi*self.alphas(mu*mu)*4./3. 91 | return cpl*R 92 | 93 | def RSub(self,fl,pa,p1,p2,p3,mu): 94 | s12 = 2.*p1*p2 95 | s13 = 2.*p1*p3 96 | s23 = 2.*p2*p3 97 | y132 = s13/(s12+s13+s23) 98 | y231 = s23/(s12+s13+s23) 99 | if y132 < self.amin or y231 < self.amin: 100 | return [ ] 101 | z1 = s12/(s12+s23) 102 | z2 = s12/(s12+s13) 103 | p13t = p1+p3-y132/(1.-y132)*p2 104 | p1t = 1./(1.-y231)*p1 105 | D132 = 1./y132 * (2./(1.-z1*(1.-y132))-(1.+z1)) 106 | D231 = 1./y231 * (2./(1.-z2*(1.-y231))-(1.+z2)) 107 | D132 *= self.ME2(fl,s12+s13+s23,(pa+p13t).M2()) 108 | D231 *= self.ME2(fl,s12+s13+s23,(pa+p1t).M2()) 109 | cpl = 8.*m.pi*self.alphas(mu*mu)*4./3. 110 | return [ cpl*D132, cpl*D231 ] 111 | 112 | def GenerateHPoint(self,lo,mu): 113 | y = pow(r.random(),1./(1.-self.ye)); 114 | w = pow(y,self.ye)/(1.-self.ye); 115 | z = pow(r.random(),1./(1.-self.ze)); 116 | w *= pow(z,self.ze)/(1.-self.ze); 117 | phi = 2.*m.pi*r.random() 118 | w *= (1.-y)/(16.*m.pi*m.pi); 119 | ij = r.randint(0,1) 120 | pe = self.MakeKinematics(z,y,phi,lo[0][2+ij].mom,lo[0][3-ij].mom) 121 | Dijk = self.RSub(lo[0][2].pid,lo[0][0].mom,pe[2*ij],pe[2-2*ij],pe[1],mu) 122 | if len(Dijk) == 0: 123 | return ( lo[0], 0. ) 124 | R = self.Real(lo[2],pe[2*ij],pe[2-2*ij],pe[1],mu) 125 | return ( [ 126 | lo[0][0],lo[0][1], 127 | Particle(21,pe[1],[2,1]), 128 | Particle(lo[0][2].pid,pe[2*ij],[1,0]), 129 | Particle(lo[0][3].pid,pe[2-2*ij],[0,2]) 130 | ], lo[1]/lo[2]*w*(R-Dijk[0]-Dijk[1]) ) 131 | 132 | def GenerateSPoint(self,lo,mu): 133 | l = m.log(mu*mu/(lo[0][2].mom+lo[0][3].mom).M2()) 134 | V = [ -2., -3. - 2.*l, -8.+m.pi*m.pi - 3.*l - l*l ] 135 | I132 = [ 1., 3./2. + l, 5.-m.pi*m.pi/2. + 3./2.*l + l*l/2. ] 136 | I231 = [ 1., 3./2. + l, 5.-m.pi*m.pi/2. + 3./2.*l + l*l/2. ] 137 | if V[0]+I132[0]+I231[0] != 0.: 138 | print "Pole check failed (double pole)" 139 | if V[1]+I132[1]+I231[1] != 0.: 140 | print "Pole check failed (single pole)" 141 | K = self.alphas(mu*mu)/(2.*m.pi)*4./3.*(V[2]+I132[2]+I231[2]) 142 | return ( lo[0], lo[1]*(1.+K) ) 143 | 144 | def GenerateMCNLOPoint(self): 145 | lo = self.GeneratePoint() 146 | if r.random() < self.ws: 147 | nlo = self.GenerateHPoint(lo,self.ecms) 148 | return ( nlo[0], nlo[1]/self.ws ) 149 | nlo = self.GenerateSPoint(lo,self.ecms) 150 | return ( nlo[0], nlo[1]/(1.-self.ws) ) 151 | -------------------------------------------------------------------------------- /matrix.py: -------------------------------------------------------------------------------- 1 | 2 | import numpy as np 3 | 4 | import math as m 5 | import random as r 6 | 7 | from vector import Vec4 8 | from particle import Particle 9 | 10 | class eetojj: 11 | 12 | def __init__(self,alphas,ecms=91.2): 13 | self.alphas = alphas 14 | self.ecms = ecms 15 | self.MZ2 = pow(91.1876,2.) 16 | self.GZ2 = pow(2.4952,2.) 17 | self.alpha = 1./128.802 18 | self.sin2tw = 0.22293 19 | 20 | def ME2(self,fl,s,t): #7.51 --- args sind 4 impulse 21 | qe = -1. 22 | ae = -0.5 23 | ve = ae - 2.*qe*self.sin2tw; 24 | qf = 2./3. if fl in [2,4] else -1./3. 25 | af = 0.5 if fl in [2,4] else -0.5 26 | vf = af - 2.*qf*self.sin2tw; 27 | kappa = 1./(4.*self.sin2tw*(1.-self.sin2tw)) 28 | chi1 = kappa * s * (s-self.MZ2)/(pow(s-self.MZ2,2.) + self.GZ2*self.MZ2); 29 | chi2 = pow(kappa * s,2.)/(pow(s-self.MZ2,2.) + self.GZ2*self.MZ2); 30 | term1 = (1+pow(1.+2.*t/s,2.))*(pow(qf*qe,2.)+2.*(qf*qe*vf*ve)*chi1+(ae*ae+ve*ve)*(af*af+vf*vf)*chi2) 31 | term2 = (1.+2.*t/s)*(4.*qe*qf*ae*af*chi1+8.*ae*ve*af*vf*chi2) 32 | return pow(4.*m.pi*self.alpha,2.)*3.*(term1+term2) 33 | 34 | def GeneratePoint(self): # hier werden 4impulse gebaut 35 | ct = 2.*r.random()-1. 36 | st = m.sqrt(1.-ct*ct) 37 | phi = 2.*m.pi*r.random() 38 | p1 = Vec4(1,st*m.cos(phi),st*m.sin(phi),ct)*self.ecms/2 39 | p2 = Vec4(p1.E,-p1.px,-p1.py,-p1.pz) 40 | pa = Vec4(self.ecms/2,0,0,self.ecms/2) 41 | pb = Vec4(self.ecms/2,0,0,-self.ecms/2) 42 | fl = r.randint(1,5) 43 | lome = self.ME2(fl,(pa+pb).M2(),(pa-p1).M2()) 44 | dxs = 5.*lome*3.89379656e8/(8.*m.pi)/(2.*pow(self.ecms,2)) # 1./8 ... ist das PS gewicht 45 | return ( [ 46 | Particle(-11,-pa), 47 | Particle(11,-pb), 48 | Particle(fl,p1,[1,0]), 49 | Particle(-fl,p2,[0,1]) 50 | ], dxs, lome ) 51 | 52 | def GenerateLOPoint(self): 53 | lo = self.GeneratePoint() 54 | return ( lo[0], lo[1] ) 55 | 56 | if __name__ == "__main__": 57 | M = eetojj(0.128) 58 | import matplotlib.pyplot as plt 59 | 60 | 61 | # Spaghetti code for the three particle case 62 | Q=100 # total momentum 63 | n=3 # number of external particles 64 | 65 | # Following Simon's notation, in the 3particle case, "i" in Algorithm 1 is 2 66 | # 67 | # we solve r= (n+1-i)*u**(n-i) - (n-i)*u**(n-1 + 1) = 2 * u - u**2 for u 68 | # 69 | # we can neglect the second solution and write u_i = u_2 = 1-sqrt(1-r_(i-1)) 70 | # = 1 - sqrt(1-r_1) 71 | # 72 | # where r_1 is our first random number 73 | 74 | def u2(r1): 75 | """ 76 | Integration variable in the n=3 case 77 | """ 78 | return 1. - np.sqrt(1.-r1) 79 | 80 | def rho(Mout, Min, mext=0.0): 81 | """ 82 | Helper function for mass term eq (5) 83 | """ 84 | M2 = Mout*Mout 85 | return 0.125 * np.sqrt( (M2 - (Min+mext)*(Min+mext)) * (M2 - (Min-mext)*(Min-mext))) / M2 86 | 87 | def rho_massless(Mout, Min): 88 | """ 89 | Helper function for mass term eq (5) 90 | """ 91 | M2 = Mout*Mout 92 | M22 = Min*Min 93 | return 0.125 * np.sqrt( M2*M2 - 2*M2*M22 + M22*M22) / M2 94 | 95 | Q_1 = Q 96 | M_1 = Q 97 | 98 | from sympy.solvers import solve 99 | from sympy import Symbol 100 | u = Symbol("u") 101 | 102 | NSAMPLES=1 103 | R_1 = np.random.rand(NSAMPLES) 104 | 105 | import time 106 | # t1 = time.time() 107 | # U2 = [min(solve(2*u - u**2 -r1, u, positive=True)) for r1 in R1] 108 | # t2 = time.time() 109 | # print("Method 1 took {} s".format(t2-t1)) 110 | 111 | t1 = time.time() 112 | U_2 = u2(R_1) 113 | t2 = time.time() 114 | print("Method 2 took {} s".format(t2-t1)) 115 | 116 | # Now the mass of the intermediary system 117 | # M_i = u2...u_i*sqrt(Q**2) 118 | # i.e. M_2 = u_2 * Q 119 | M_2 = U_2 * Q 120 | 121 | 122 | # Now build momenta 123 | # q_i = 4*M_(i-1) * rho (M_(i-1), M_i, 0) 124 | # i.e. = 4 * M_1 * rho(M_1, M_2) 125 | 126 | t1 = time.time() 127 | q_2 = 4*M_1 * rho_massless(M_1, M_2) 128 | t2 = time.time() 129 | print("Method 1 took {} s".format(t2-t1)) 130 | # t1 = time.time() 131 | # q_22 = 4*M_1 *rho(M_1, M_2) 132 | # t2 = time.time() 133 | # print("Method 2 took {} s".format(t2-t1)) 134 | 135 | # Get costheta_i in [0,1] and phi_i in [0,2pi] 136 | # using random numbers r_(n-5+2*i) and r_(n-4+2*i) 137 | # i.e. r_2 and r_3 138 | R_2 = np.random.rand(NSAMPLES) 139 | R_3 = np.random.rand(NSAMPLES) 140 | CT_2 = 2.*R_2-1. 141 | PHI_2 = 2.*np.pi * R_3 142 | 143 | # Three momenta come first 144 | # p_(i-1) = q_i * [ 145 | # cos(phi_i)*sqrt(1-costheta_i**2) 146 | # sin(phi_i)*sqrt(1-costheta_i**2) 147 | # costheta_i 148 | # ] 149 | COSPHI_2 = np.cos(PHI_2) 150 | SINPHI_2 = np.sin(PHI_2) 151 | TMP = np.sqrt(1.-CT_2*CT_2) 152 | 153 | # 4-mom vectors as array 154 | MOM = np.empty((NSAMPLES,4)) 155 | MOM[:,0] = q_2 156 | MOM[:,1] = q_2 * COSPHI_2 * TMP 157 | MOM[:,2] = q_2 * SINPHI_2 * TMP 158 | MOM[:,3] = q_2 * CT_2 159 | 160 | # Q_2 4-vectors 161 | Q_2 = np.empty((NSAMPLES, 4)) 162 | Q_2[:,0] = np.sqrt(q_2*q_2 + M_2*M_2) 163 | Q_2[:,(1,2,3)] = - MOM[:,(1,2,3)] 164 | 165 | 166 | t1 = time.time() 167 | vP1 = [Vec4(*m) for m in MOM] # p1 --- but in CMS 168 | vQ2 = [Vec4(*q) for q in Q_2] # Q2 --- but in CMS 169 | t2 = time.time() 170 | print("Conversion took {} s".format(t2-t1)) 171 | 172 | # TODO understand boost --- also if n>3 there is also a boost of Q_2 required to proceed correctly 173 | # 174 | # NOTE in the final step, i.e. no more intermediate steps, M_i becomes 0 175 | # and the final 4-momenta are (in the correponding CMS) simply +/- MOM 176 | q_3 = 4*M_2 * rho_massless(M_2, 0) 177 | 178 | # in the n=3 case, we are done with intermediate steps and only need to draw two more random numbers 179 | R_4 = np.random.rand(NSAMPLES) 180 | R_5 = np.random.rand(NSAMPLES) 181 | CT_3 = 2.*R_4-1. 182 | PHI_3 = 2.*np.pi * R_5 183 | 184 | COSPHI_3 = np.cos(PHI_3) 185 | SINPHI_3 = np.sin(PHI_3) 186 | TMP = np.sqrt(1.-CT_3*CT_3) 187 | 188 | # 4-mom vectors as array 189 | MOMLAST = np.empty((NSAMPLES,4)) 190 | MOMLAST[:,0] = q_3 191 | MOMLAST[:,1] = q_3 * COSPHI_3 * TMP 192 | MOMLAST[:,2] = q_3 * SINPHI_3 * TMP 193 | MOMLAST[:,3] = q_3 * CT_3 194 | 195 | MOMLAST_minus = np.empty((NSAMPLES,4)) 196 | MOMLAST_minus[:,0] = q_3 197 | MOMLAST_minus[:,(1,2,3)] = - MOMLAST[:,(1,2,3)] 198 | vP2 = [Vec4(*m) for m in MOMLAST] # p2 --- but in CMS 199 | vP3 = [Vec4(*m) for m in MOMLAST_minus] # p3 --- but in CMS 200 | from IPython import embed 201 | embed() 202 | 203 | 204 | -------------------------------------------------------------------------------- /algorithm1.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | from vector import Vec4 4 | 5 | def u_2(r): 6 | """ 7 | Integration variable u_2 --- solution for r = 2u^1 - 1u^2 8 | """ 9 | return 1. - np.sqrt(1.-r) 10 | 11 | # def u3(r): 12 | # kappa = np.cbrt( 2*np.sqrt(r*(r-1) ) -2*r +1 ) 13 | # return 0.5*(kappa + 1./kappa + 1) 14 | 15 | def f(x, a, r): 16 | """ 17 | The equation ax^(a-1) - (a-1)x^a - r = 0 18 | To be used as argument in solver 19 | """ 20 | return a*x**(a-1) - (a-1)*x**a - r 21 | 22 | def fp(x, a): 23 | """ 24 | First derivative of f 25 | """ 26 | return a*(a-1)*(x**(a-2) - x**(a-1)) 27 | 28 | def fpp(x, a): 29 | """ 30 | Second derivative of 31 | """ 32 | return a*(a-1)*((a-2)*x**(a-3) - (a-1)*x**(a-2)) 33 | 34 | def get_u(a, r): 35 | """ 36 | Solve f for u 37 | 38 | a = n + 1 -i in Simon's notation 39 | 40 | The lowest order case is n=3 and i = 2, i.e. a = 2 41 | """ 42 | if a < 2 : raise Exception("a = {} not implemented".format(a)) 43 | 44 | from scipy import optimize 45 | if a == 2: return u_2(r) 46 | else: 47 | return optimize.newton(lambda x : f(x, a, r), r, fprime=lambda x: fp(x,a), fprime2=lambda x: fpp(x,a)) 48 | 49 | def rho(Min, Mout, mext=0.0): 50 | """ 51 | Helper function for mass term eq (5) 52 | """ 53 | M2 = Min*Min 54 | return 0.125 * np.sqrt( (M2 - (Mout+mext)*(Mout+mext)) * (M2 - (Mout-mext)*(Mout-mext))) / M2 55 | 56 | def rho_massless(Min, Mout): 57 | """ 58 | Helper function for mass term eq (5) 59 | """ 60 | M2 = Min*Min 61 | M22 = Mout*Mout 62 | return 0.125 * np.sqrt( M2*M2 - 2*M2*M22 + M22*M22) / M2 63 | 64 | def ME_ESW(P): 65 | """ 66 | Calculate the matrix element for g(p1) g(p2) --> g(p3) g(p4) g(p5) 67 | 68 | Using eq (7.51) in QCD for collider physics. 69 | 70 | P ... list of 4 momentum vectors 71 | """ 72 | from itertools import permutations 73 | permutations=list(permutations([0,1,2,3,4])) # All 120 permutations 74 | 75 | # M = const * A * B / C 76 | 77 | # A = sum_permutations {1 2} ^ 4 78 | A = 0 79 | B = 0 80 | for i in permutations: 81 | A+= (P[i[0]] * P[i[1]])**4 82 | B+= (P[i[0]] * P[i[1]]) * (P[i[1]] * P[i[2]]) * (P[i[2]] * P[i[3]]) * (P[i[3]] * P[i[4]]) * (P[i[4]] * P[i[0]]) 83 | 84 | C = 1 85 | for i in range(5): 86 | for j in range(5): 87 | if i g(p3) g(p4) g(p5) 96 | 97 | Using eq (18) in Berends et al, Phys Let B 103 (1981) p 124 ff. 98 | 99 | P ... list of 4 momentum vectors 100 | """ 101 | from itertools import permutations, combinations 102 | permutations= [ 103 | (0,1,2,3,4), 104 | (0,1,2,4,3), 105 | (0,1,3,2,4), 106 | (0,1,3,4,2), 107 | (0,1,4,2,3), 108 | (0,1,4,3,2), 109 | (0,2,1,3,4), 110 | (0,2,1,4,3), 111 | (0,2,3,1,4), 112 | (0,2,4,1,3), 113 | (0,3,1,2,4), 114 | (0,3,2,1,4), 115 | ] 116 | 117 | kpermutations = list(combinations([0,1,2,3,4], 2)) 118 | 119 | # M = const * A * B / C 120 | 121 | # A = sum_permutations {1 2} ^ 4 122 | A = 0 123 | for i in kpermutations: 124 | A+= (P[i[0]] * P[i[1]])**4 125 | 126 | B = 0 127 | for i in permutations: 128 | # print("(k{} * k{})^4".format(i[0]+1, i[1]+1)) 129 | B+= (P[i[0]] * P[i[1]]) * (P[i[1]] * P[i[2]]) * (P[i[2]] * P[i[3]]) * (P[i[3]] * P[i[4]]) * (P[i[4]] * P[i[0]]) 130 | 131 | C = 1 132 | for i in range(5): 133 | for j in range(5): 134 | if i =3 for the whole thing to make sense, exiting") 180 | sys.exit(1) 181 | 182 | # This is the 4-Vector of the initial blob of energy 183 | Q = Vec4(100,0,0,10) 184 | Q1 = Q 185 | Qabs = np.sqrt(Q*Q) 186 | M1 = Qabs 187 | 188 | # Storage of intermediate Masses, Qs 189 | M = [M1] 190 | ALLQ =[Q1] 191 | 192 | # The final momenta 193 | MOM = [] 194 | 195 | U, R = [], [] # Store the u and random numbers r 196 | for i in range(2, NP+1): 197 | # print("now i = {}".format(i)) 198 | if i < NP: 199 | # print("Solving for u_{}, M_{}".format(i, i)) 200 | r = np.random.rand() 201 | u = get_u(NP+1-i, r) 202 | U.append(u) 203 | R.append(r) 204 | _M = np.prod(U)*Qabs # M_i 205 | else: 206 | _M = 0 207 | # print("Got M_{}={}".format(i, _M)) 208 | M.append(_M) 209 | 210 | q = 4*M[-2] * rho_massless(M[-2], M[-1]) 211 | # Random numbers for costheta and phi 212 | costheta = 2*np.random.rand() -1 213 | phi = np.pi*np.random.rand() 214 | 215 | # Generated 4 Vectors 216 | # p_(i-1) 217 | p = q*Vec4(1, np.cos(phi)*np.sqrt(1. - costheta*costheta), np.sin(phi)*np.sqrt(1. - costheta*costheta), costheta) 218 | # print("p_{} = {}".format(i-1, p)) 219 | 220 | # now Q_i 221 | _Q = Vec4(np.sqrt(q*q + M[-1]*M[-1]), -p.px, -p.py, -p.pz) 222 | ALLQ.append(_Q) 223 | # print("Q_{} = {}".format(i, _Q)) 224 | 225 | # TODO ask Stefan how boost is supposed to work with his class 226 | # boostVector = Vec4(ALLQ[-1][0]/ALLQ[-1].E, ALLQ[-1][1]/ALLQ[-1].E, ALLQ[-1][2]/ALLQ[-1].E, ALLQ[-1][3]/ALLQ[-2].E) 227 | boostVector = ALLQ[0]-ALLQ[-1] 228 | 229 | p.BoostBack(boostVector) 230 | MOM.append(p) 231 | _Q.BoostBack(boostVector) 232 | MOM.append(_Q) 233 | 234 | 235 | for num, mom in enumerate(MOM): 236 | print("p_{} = {}".format(num+1, mom)) 237 | 238 | 239 | 240 | from IPython import embed 241 | embed() 242 | -------------------------------------------------------------------------------- /algorithm1_stefan.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | from vector import Vec4 4 | 5 | def u_2(r): 6 | """ 7 | Integration variable u_2 --- solution for r = 2u^1 - 1u^2 8 | """ 9 | return 1. - np.sqrt(1.-r) 10 | 11 | def u_3(r): 12 | """ 13 | Integration variable u_3 --- solution for r = 3u^2 - 2u^3 14 | """ 15 | x = pow(1.-2.*r+2.*np.sqrt(r*(r-1.)+0.j),1./3.) 16 | y = (2.-(1.-1.j*np.sqrt(3.))/x-(1.+1.j*np.sqrt(3.))*x)/4. 17 | return y.real 18 | 19 | def u_4(r): 20 | """ 21 | Integration variable u_4 --- solution for r = 4u^3 - 3u^4 22 | """ 23 | y = pow(r+np.sqrt(r*r*(1-r)+0.j),1./3.) 24 | x = 3./2.*(r/y+y) 25 | y = np.sqrt(1.+x) 26 | z = (1.+y-np.sqrt(2.-x+2./y))/3. 27 | return z.real 28 | 29 | def f(x, a, r): 30 | """ 31 | The equation ax^(a-1) - (a-1)x^a - r = 0 32 | To be used as argument in solver 33 | """ 34 | return a*x**(a-1) - (a-1)*x**a - r 35 | 36 | def fp(x, a): 37 | """ 38 | First derivative of f 39 | """ 40 | return a*(a-1)*(x**(a-2) - x**(a-1)) 41 | 42 | def fpp(x, a): 43 | """ 44 | Second derivative of 45 | """ 46 | return a*(a-1)*((a-2)*x**(a-3) - (a-1)*x**(a-2)) 47 | 48 | def get_u(a, r): 49 | """ 50 | Solve f for u 51 | 52 | a = n + 1 -i in Simon's notation 53 | 54 | The lowest order case is n=3 and i = 2, i.e. a = 2 55 | """ 56 | if a < 2 : raise Exception("a = {} not implemented".format(a)) 57 | 58 | from scipy import optimize 59 | if a == 2: return u_2(r) 60 | elif a == 3: return u_3(r) 61 | elif a == 4: return u_4(r) 62 | else: 63 | return optimize.newton(lambda x : f(x, a, r), r, fprime=lambda x: fp(x,a), fprime2=lambda x: fpp(x,a)) 64 | 65 | def rho(Min, Mout, mext=0.0): 66 | """ 67 | Helper function for mass term eq (5) 68 | """ 69 | M2 = Min*Min 70 | return 0.125 * np.sqrt( (M2 - (Mout+mext)*(Mout+mext)) * (M2 - (Mout-mext)*(Mout-mext))) / M2 71 | 72 | def rho_massless(Min, Mout): 73 | """ 74 | Helper function for mass term eq (5) 75 | """ 76 | M2 = Min*Min 77 | M22 = Mout*Mout 78 | return 0.125 * np.sqrt( M2*M2 - 2*M2*M22 + M22*M22) / M2 79 | 80 | def generate_point(pa,pb,rans): 81 | 82 | # The final momenta 83 | MOM = [ -rans[-1]*pa, -rans[-2]*pb ] 84 | _Q = -MOM[0]-MOM[1] 85 | 86 | # Storage of intermediate Masses, Qs 87 | M = [_Q.M()] 88 | ALLQ =[_Q] 89 | 90 | U, R = [], [] # Store the u and random numbers r 91 | for i in range(2, NP+1): 92 | # print("now i = {}".format(i)) 93 | if i < NP: 94 | # print("Solving for u_{}, M_{}".format(i, i)) 95 | r = rans[3*(i-2)+2] 96 | u = get_u(NP+1-i, r) 97 | U.append(u) 98 | R.append(r) 99 | # Simon's paper must be wrong here, check 100 | _M = np.sqrt(u*_Q.M2()) # M_i^2 101 | else: 102 | _M = 0 103 | # print("Got M_{}={}".format(i, _M)) 104 | M.append(_M) 105 | 106 | q = 4*M[-2] * rho_massless(M[-2], M[-1]) 107 | # Random numbers for costheta and phi 108 | costheta = 2*rans[3*(i-2)] - 1 109 | phi = 2.*np.pi*rans[3*(i-2)+1] 110 | 111 | # Generated 4 Vectors 112 | # p_(i-1) 113 | sintheta = np.sqrt(1. - costheta*costheta) 114 | p = q*Vec4(1, np.cos(phi)*sintheta, np.sin(phi)*sintheta, costheta) 115 | # print("p_{} = {} {}".format(i+1, p, np.sqrt(abs(p.M2())))) 116 | 117 | # now Q_i 118 | _Q = Vec4(np.sqrt(q*q + M[-1]*M[-1]), -p.px, -p.py, -p.pz) 119 | # print("Q_{} = {} {}".format(i, _Q, np.sqrt(abs(_Q.M2())))) 120 | 121 | p = ALLQ[i-2].BoostBack(p) 122 | _Q = ALLQ[i-2].BoostBack(_Q) 123 | # print ALLQ[i-2]-_Q-p 124 | # print "p boosted ",p,p.M2() 125 | # print "Q boosted ",_Q,np.sqrt(abs(_Q.M2())) 126 | # print "sum p+Q ",(p+_Q),(p+_Q).M() 127 | MOM.append(p) 128 | ALLQ.append(_Q) 129 | MOM.append(_Q) 130 | return MOM 131 | 132 | def generate_weight(pa,pb,mom): 133 | Q = -mom[0]-mom[1] 134 | rans = [] 135 | for i in range(2, NP+1): 136 | # print("now i = {}".format(i)) 137 | p = Q.Boost(mom[i]) 138 | # print 'p = ',p 139 | costh = p[3]/p.P() 140 | phi = p.Phi() 141 | if phi < 0: phi += 2.*np.pi 142 | # print "phi = ",phi 143 | rans.append((1+costh)/2.) 144 | rans.append(phi/(2.*np.pi)) 145 | if i < NP: 146 | m = (Q-mom[i]).M2() / Q.M2() 147 | u = f(m, NP+1-i, 0) 148 | # print Q.M2(),(Q-mom[i]).M2(),(mom[3]+mom[4]).M2(),m,u 149 | # print Q 150 | Q -= mom[i] 151 | # print Q 152 | rans.append(u) 153 | else: 154 | _M = 0 155 | rans.append(-(mom[1]*pa)/(pa*pb)) 156 | rans.append(-(mom[0]*pb)/(pa*pb)) 157 | return rans 158 | 159 | def ME_ESW(P): 160 | """ 161 | Calculate the matrix element for g(p1) g(p2) --> g(p3) g(p4) g(p5) 162 | 163 | Using eq (7.51) in QCD for collider physics. 164 | 165 | P ... list of 4 momentum vectors 166 | """ 167 | from itertools import permutations 168 | permutations=list(permutations([0,1,2,3,4])) # All 120 permutations 169 | 170 | # M = const * A * B / C 171 | 172 | # A = sum_permutations {1 2} ^ 4 173 | A = 0 174 | B = 0 175 | for i in permutations: 176 | A+= (P[i[0]] * P[i[1]])**4 177 | B+= (P[i[0]] * P[i[1]]) * (P[i[1]] * P[i[2]]) * (P[i[2]] * P[i[3]]) * (P[i[3]] * P[i[4]]) * (P[i[4]] * P[i[0]]) 178 | 179 | C = 1 180 | for i in range(5): 181 | for j in range(5): 182 | if i g(p3) g(p4) g(p5) 191 | 192 | Using eq (18) in Berends et al, Phys Let B 103 (1981) p 124 ff. 193 | 194 | P ... list of 4 momentum vectors 195 | """ 196 | from itertools import permutations, combinations 197 | permutations= [ 198 | (0,1,2,3,4), 199 | (0,1,2,4,3), 200 | (0,1,3,2,4), 201 | (0,1,3,4,2), 202 | (0,1,4,2,3), 203 | (0,1,4,3,2), 204 | (0,2,1,3,4), 205 | (0,2,1,4,3), 206 | (0,2,3,1,4), 207 | (0,2,4,1,3), 208 | (0,3,1,2,4), 209 | (0,3,2,1,4), 210 | ] 211 | 212 | kpermutations = list(combinations([0,1,2,3,4], 2)) 213 | 214 | # M = const * A * B / C 215 | 216 | # A = sum_permutations {1 2} ^ 4 217 | A = 0 218 | for i in kpermutations: 219 | A+= (P[i[0]] * P[i[1]])**4 220 | 221 | B = 0 222 | for i in permutations: 223 | # print("(k{} * k{})^4".format(i[0]+1, i[1]+1)) 224 | B+= (P[i[0]] * P[i[1]]) * (P[i[1]] * P[i[2]]) * (P[i[2]] * P[i[3]]) * (P[i[3]] * P[i[4]]) * (P[i[4]] * P[i[0]]) 225 | 226 | C = 1 227 | for i in range(5): 228 | for j in range(5): 229 | if i =3 for the whole thing to make sense, exiting") 249 | sys.exit(1) 250 | 251 | rans = [ np.random.rand() for i in range(0,3*NP-4+2) ] 252 | 253 | moms = generate_point(pa,pb,rans) 254 | 255 | msum = Vec4() 256 | for num, mom in enumerate(moms): 257 | msum += mom 258 | print("p_{} = {} {}".format(num+1, mom, mom.M2())) 259 | print("Mom sum {}".format(msum)) 260 | 261 | ranc = generate_weight(pa,pb,moms) 262 | 263 | for r in range(0,len(rans)): 264 | print("r_{} = {} -> dev. {}".format(r, ranc[r], ranc[r]/rans[r]-1)) 265 | 266 | 267 | print("120*Berends: {:.20f}".format(120*ME_PLB(moms))) 268 | print("Ellis: {:.20f}".format(ME_ESW(moms))) 269 | 270 | -------------------------------------------------------------------------------- /flatmc.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from numba import jit, njit 3 | 4 | from vector import Vec4 5 | 6 | @njit 7 | def u_2(r): 8 | """ 9 | Integration variable u_2 --- solution for r = 2u^1 - 1u^2 10 | """ 11 | return 1. - np.sqrt(1.-r) 12 | 13 | @njit(fastmath=True) 14 | def u_3(r): 15 | """ 16 | Integration variable u_3 --- solution for r = 3u^2 - 2u^3 17 | """ 18 | x = pow(1.-2.*r+2.*np.sqrt(r*(r-1.)+0.j),1./3.) 19 | y = (2.-(1.-1.j*np.sqrt(3.))/x-(1.+1.j*np.sqrt(3.))*x)/4. 20 | return y.real 21 | 22 | @njit(fastmath=True) 23 | def u_4(r): 24 | """ 25 | Integration variable u_4 --- solution for r = 4u^3 - 3u^4 26 | """ 27 | y = pow(r+np.sqrt(r*r*(1-r)+0.j),1./3.) 28 | x = 3./2.*(r/y+y) 29 | y = np.sqrt(1.+x) 30 | z = (1.+y-np.sqrt(2.-x+2./y))/3. 31 | return z.real 32 | 33 | @njit(fastmath=True) 34 | def f(x, a, r): 35 | """ 36 | The equation ax^(a-1) - (a-1)x^a - r = 0 37 | To be used as argument in solver 38 | """ 39 | return a*x**(a-1) - (a-1)*x**a - r 40 | 41 | @njit(fastmath=True) 42 | def fp(x, a): 43 | """ 44 | First derivative of f 45 | """ 46 | return a*(a-1)*(x**(a-2) - x**(a-1)) 47 | 48 | @njit(fastmath=True) 49 | def fpp(x, a): 50 | """ 51 | Second derivative of 52 | """ 53 | return a*(a-1)*((a-2)*x**(a-3) - (a-1)*x**(a-2)) 54 | 55 | def get_u(a, r): 56 | """ 57 | Solve f for u 58 | 59 | a = n + 1 -i in Simon's notation 60 | 61 | The lowest order case is n=3 and i = 2, i.e. a = 2 62 | """ 63 | if a < 2 : raise Exception("a = {} not implemented".format(a)) 64 | 65 | from scipy import optimize 66 | if a == 2: return u_2(r) 67 | elif a == 3: return u_3(r) 68 | elif a == 4: return u_4(r) 69 | else: 70 | return optimize.newton(lambda x : f(x, a, r), r, fprime=lambda x: fp(x,a), fprime2=lambda x: fpp(x,a)) 71 | 72 | def rho(Min, Mout, mext=0.0): 73 | """ 74 | Helper function for mass term eq (5) 75 | """ 76 | M2 = Min*Min 77 | return 0.125 * np.sqrt( (M2 - (Mout+mext)*(Mout+mext)) * (M2 - (Mout-mext)*(Mout-mext))) / M2 78 | 79 | def rho_massless(Min, Mout): 80 | """ 81 | Helper function for mass term eq (5) 82 | """ 83 | M2 = Min*Min 84 | M22 = Mout*Mout 85 | return 0.125 * np.sqrt( M2*M2 - 2*M2*M22 + M22*M22) / M2 86 | 87 | def generate_point(pa,pb,rans): 88 | 89 | # The final momenta 90 | # MOM = [ -rans[-1]*pa, -rans[-2]*pb ] 91 | MOM = [ -pa, -pb ] # NOTE this fixes the incoming momenta 92 | _Q = -MOM[0]-MOM[1] 93 | 94 | # Storage of intermediate Masses, Qs 95 | M = [_Q.M()] 96 | ALLQ =[_Q] 97 | 98 | U, R = [], [] # Store the u and random numbers r 99 | for i in range(2, NP+1): 100 | # print("now i = {}".format(i)) 101 | if i < NP: 102 | # print("Solving for u_{}, M_{}".format(i, i)) 103 | r = rans[3*(i-2)+2] 104 | u = get_u(NP+1-i, r) 105 | U.append(u) 106 | R.append(r) 107 | # Simon's paper must be wrong here, check 108 | _M = np.sqrt(u*_Q.M2()) # M_i^2 109 | else: 110 | _M = 0 111 | # print("Got M_{}={}".format(i, _M)) 112 | M.append(_M) 113 | 114 | q = 4*M[-2] * rho_massless(M[-2], M[-1]) 115 | # Random numbers for costheta and phi 116 | costheta = 2*rans[3*(i-2)] - 1 117 | phi = 2.*np.pi*rans[3*(i-2)+1] 118 | 119 | # Generated 4 Vectors 120 | # p_(i-1) 121 | sintheta = np.sqrt(1. - costheta*costheta) 122 | p = q*Vec4(1, np.cos(phi)*sintheta, np.sin(phi)*sintheta, costheta) 123 | # print("p_{} = {} {}".format(i+1, p, np.sqrt(abs(p.M2())))) 124 | 125 | # now Q_i 126 | _Q = Vec4(np.sqrt(q*q + M[-1]*M[-1]), -p.px, -p.py, -p.pz) 127 | # print("Q_{} = {} {}".format(i, _Q, np.sqrt(abs(_Q.M2())))) 128 | 129 | p = ALLQ[i-2].BoostBack(p) 130 | _Q = ALLQ[i-2].BoostBack(_Q) 131 | # print ALLQ[i-2]-_Q-p 132 | # print "p boosted ",p,p.M2() 133 | # print "Q boosted ",_Q,np.sqrt(abs(_Q.M2())) 134 | # print "sum p+Q ",(p+_Q),(p+_Q).M() 135 | MOM.append(p) 136 | ALLQ.append(_Q) 137 | MOM.append(_Q) 138 | return MOM 139 | 140 | def generate_weight(pa,pb,mom): 141 | Q = -mom[0]-mom[1] 142 | rans = [] 143 | for i in range(2, NP+1): 144 | # print("now i = {}".format(i)) 145 | p = Q.Boost(mom[i]) 146 | # print 'p = ',p 147 | costh = p[3]/p.P() 148 | phi = p.Phi() 149 | if phi < 0: phi += 2.*np.pi 150 | # print "phi = ",phi 151 | rans.append((1+costh)/2.) 152 | rans.append(phi/(2.*np.pi)) 153 | if i < NP: 154 | m = (Q-mom[i]).M2() / Q.M2() 155 | u = f(m, NP+1-i, 0) 156 | # print Q.M2(),(Q-mom[i]).M2(),(mom[3]+mom[4]).M2(),m,u 157 | # print Q 158 | Q -= mom[i] 159 | # print Q 160 | rans.append(u) 161 | else: 162 | _M = 0 163 | rans.append(-(mom[1]*pa)/(pa*pb)) 164 | rans.append(-(mom[0]*pb)/(pa*pb)) 165 | return rans 166 | 167 | def ME_ESW(P): 168 | """ 169 | Calculate the matrix element for g(p1) g(p2) --> g(p3) g(p4) g(p5) 170 | 171 | Using eq (7.51) in QCD for collider physics. 172 | 173 | P ... list of 4 momentum vectors 174 | """ 175 | from itertools import permutations 176 | permutations=list(permutations([0,1,2,3,4])) # All 120 permutations 177 | 178 | # M = const * A * B / C 179 | 180 | # A = sum_permutations {1 2} ^ 4 181 | A = 0 182 | B = 0 183 | for i in permutations: 184 | A+= (P[i[0]] * P[i[1]])**4 185 | B+= (P[i[0]] * P[i[1]]) * (P[i[1]] * P[i[2]]) * (P[i[2]] * P[i[3]]) * (P[i[3]] * P[i[4]]) * (P[i[4]] * P[i[0]]) 186 | 187 | C = 1 188 | for i in range(5): 189 | for j in range(5): 190 | if i g(p3) g(p4) g(p5) 199 | 200 | Using eq (18) in Berends et al, Phys Let B 103 (1981) p 124 ff. 201 | 202 | P ... list of 4 momentum vectors 203 | """ 204 | from itertools import permutations, combinations 205 | permutations= [ 206 | (0,1,2,3,4), 207 | (0,1,2,4,3), 208 | (0,1,3,2,4), 209 | (0,1,3,4,2), 210 | (0,1,4,2,3), 211 | (0,1,4,3,2), 212 | (0,2,1,3,4), 213 | (0,2,1,4,3), 214 | (0,2,3,1,4), 215 | (0,2,4,1,3), 216 | (0,3,1,2,4), 217 | (0,3,2,1,4), 218 | ] 219 | 220 | kpermutations = list(combinations([0,1,2,3,4], 2)) 221 | 222 | # M = const * A * B / C 223 | 224 | # A = sum_permutations {1 2} ^ 4 225 | A = 0 226 | for i in kpermutations: 227 | A+= (P[i[0]] * P[i[1]])**4 228 | 229 | B = 0 230 | for i in permutations: 231 | # print("(k{} * k{})^4".format(i[0]+1, i[1]+1)) 232 | B+= (P[i[0]] * P[i[1]]) * (P[i[1]] * P[i[2]]) * (P[i[2]] * P[i[3]]) * (P[i[3]] * P[i[4]]) * (P[i[4]] * P[i[0]]) 233 | 234 | C = 1 235 | for i in range(5): 236 | for j in range(5): 237 | if i =3 for the whole thing to make sense, exiting") 257 | sys.exit(1) 258 | 259 | rans = [ np.random.rand() for i in range(0,3*NP-4+2) ] 260 | 261 | moms = generate_point(pa,pb,rans) 262 | 263 | msum = Vec4() 264 | for num, mom in enumerate(moms): 265 | msum += mom 266 | print("p_{} = {} {}".format(num+1, mom, mom.M2())) 267 | print("Mom sum {}".format(msum)) 268 | 269 | ranc = generate_weight(pa,pb,moms) 270 | 271 | for r in range(0,len(rans)): 272 | print("r_{} = {} -> dev. {}".format(r, ranc[r], ranc[r]/rans[r]-1)) 273 | 274 | 275 | print("120*Berends: {:.20f}".format(120*ME_PLB(moms))) 276 | print("Ellis: {:.20f}".format(ME_ESW(moms))) 277 | 278 | 279 | import time 280 | t1=time.time() 281 | Y = [] 282 | NSAMPLES=int(sys.argv[2]) 283 | X=[] 284 | for _ in range(NSAMPLES): 285 | rans = [ np.random.rand() for i in range(0,3*NP-4+2) ] 286 | X.append(rans[0:5]) 287 | moms = generate_point(pa,pb,rans) 288 | Y.append(ME_PLB(moms)) 289 | t2=time.time() 290 | print("Generation of {} configuration took {} seconds".format(NSAMPLES, t2-t1)) 291 | 292 | 293 | import apprentice 294 | t1=time.time() 295 | apprentice.RationalApproximation(X,Y, order=(5,5), strategy=3) 296 | t2=time.time() 297 | print("Approximation took {} seconds".format(t2-t1)) 298 | 299 | # from IPython import embed 300 | # embed() 301 | 302 | # import matplotlib.pyplot as plt 303 | # plt.style.use("ggplot") 304 | # plt.xlabel("$\log_{10}(ME)$") 305 | # plt.hist(np.log10(Y), bins=51,histtype='step', label="Exact") 306 | # plt.yscale("log") 307 | 308 | # import apprentice 309 | # S=apprentice.Scaler(X) 310 | # XX = S.scale(X) 311 | 312 | # m=int(sys.argv[3]) 313 | # n=int(sys.argv[4]) 314 | # # R = apprentice.RationalApproximation(XX, H, order=(m,n)) 315 | # # R.save("approx_{}_{}.json".format(m,n)) 316 | # R=apprentice.RationalApproximation(fname="approx_1_12.json") 317 | # from IPython import embed 318 | # embed() 319 | # HH = [] 320 | # t1=time.time() 321 | # for x in XX: 322 | # HH.append(R(x)) 323 | # t2=time.time() 324 | # print("Evaluation of {} configuration took {} seconds".format(NSAMPLES, t2-t1)) 325 | 326 | # plt.hist(np.log10(HH), bins=51,histtype='step', label="Approx") 327 | # plt.legend() 328 | # plt.savefig("test_{}_{}.pdf".format(m,n)) 329 | 330 | # res = [] 331 | # for num, x in enumerate(XX): 332 | # res.append((R(x) - H[num])/H[num]) 333 | 334 | # plt.clf() 335 | # plt.hist(res, bins=5001) 336 | # plt.xlim((-10,10)) 337 | # plt.yscale("log") 338 | # plt.savefig("residual_{}_{}.pdf".format(m,n)) 339 | # sys.exit(1) 340 | 341 | 342 | # for m in range(1, 2): 343 | # for n in range(5, 15): 344 | # print("Now ({},{})".format(m,n)) 345 | # R = apprentice.RationalApproximation(XX, H, order=(m,n)) 346 | # R.save("approx_{}_{}.json".format(m,n)) 347 | 348 | # res = [] 349 | # for num, x in enumerate(XX): 350 | # res.append((R(x) - H[num])/H[num]) 351 | 352 | # plt.clf() 353 | # plt.hist(res, bins=5000) 354 | # plt.xlim((-10,10)) 355 | # plt.savefig("residual_{}_{}.pdf".format(m,n)) 356 | 357 | # m=int(sys.argv[3]) 358 | # n=int(sys.argv[4]) 359 | # R = apprentice.RationalApproximation(XX, H, order=(m,n)) 360 | # R.save("approx_{}_{}.json".format(m,n)) 361 | # # from IPython import embed 362 | # # embed() 363 | 364 | # res = [] 365 | # for num, x in enumerate(XX): 366 | # res.append((R(x) - H[num])/H[num]) 367 | 368 | # plt.clf() 369 | # plt.hist(res, bins=5000) 370 | # plt.xlim((-10,10)) 371 | # plt.savefig("residual_{}_{}.pdf".format(m,n)) 372 | 373 | # from IPython import embed 374 | # embed() 375 | 376 | --------------------------------------------------------------------------------