You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
defdo_wick(string):
debug=Falseifdebug: print('Input string:',string)
idx_orb=0idx_op=2pos= [iforiinrange(len(string))]
# Extraction of the operators## By class of orb### ii_op, pos_i_op=extract_op(string,'i',idx_orb,pos)
ifdebug: print('i op:',i_op,'\nPos i op:',pos_i_op)
### aa_op, pos_a_op=extract_op(string,'a',idx_orb,pos)
ifdebug: print('a op:',a_op,'\nPos a op:',pos_a_op)
## By class of op### i+i_crea, pos_i_crea=extract_op(i_op,'+',idx_op,pos_i_op)
ifdebug: print('i+:',i_crea,'\nPos i+:',pos_i_crea)
### i-i_anni, pos_i_anni=extract_op(i_op,'-',idx_op,pos_i_op)
ifdebug: print('i-:',i_anni,'\nPos i-:',pos_i_anni)
### a+a_crea, pos_a_crea=extract_op(a_op,'+',idx_op,pos_a_op)
ifdebug: print('a+:',a_crea,'\nPos a+:',pos_a_crea)
### a-a_anni, pos_a_anni=extract_op(a_op,'-',idx_op,pos_a_op)
ifdebug: print('a-:',a_anni,'\nPos a-:',pos_a_anni)
# Build delta## i+ i-delta_i=build_delta(i_crea,i_anni,pos_i_crea,pos_i_anni)
ifdebug: print('Delta i:', delta_i)
## a- a+delta_a=build_delta(a_anni,a_crea,pos_a_anni,pos_a_crea)
ifdebug: print('Delta a:', delta_a)
#sys.exit()# Creation of all the products of hole deltasres_i=combine_one_class_delta(delta_i,i_op,string)
res_i.insert(0,[[]])
ifdebug: print('res_i (possible products of i deltas):',res_i)
# Creation of all the products of particle deltasres_a=combine_one_class_delta(delta_a,a_op,string)
res_a.insert(0,[[]])
ifdebug: print('res_a (possible products of a deltas):',res_a)
# Combination of the products of kronecker deltas coming from different classes of orbitalsres= []
# Iteration over the order (order <=> number of deltas) for ifororder_iinres_i:
# Iteration over the list of product of deltas i of a given orderforlist_delta_iinorder_i:
# As for ifororder_ainres_a:
# As for iforlist_delta_ainorder_a:
# If there is at least one term for aiflen(list_delta_a) >0:
# the different deltas a are append after the i onestmp=copy.deepcopy(list_delta_i)
fordelta_ainlist_delta_a:
tmp.append(delta_a)
res.append(tmp)
# If there is no a delta, we just keep the i oneselse:
tmp=copy.deepcopy(list_delta_i)
res.append(tmp)
# Ordering of the terms by increasing number of deltasmax_len=0foreleminres:
iflen(elem) >max_len:
max_len=len(elem)
# Reordering of the list of deltas depending on the number of deltastmp_ordered= [[] foriinrange(max_len+1)]
foreleminres:
tmp_ordered[len(elem)].append(elem)
# Finally the right orderlist_deltas= []
forl_deltasintmp_ordered:
foreleminl_deltas:
list_deltas.append(elem)
list_signs= []
foreleminlist_deltas:
list_signs.append(extract_sign(elem,string))
# copy of the initial stringlist_str= [stringforiinrange(len(list_signs))]
# Removing the op of the string implied in a contractionacc= []
fors,dinzip(list_str,list_deltas):
tmp= []
forelemins:
is_contracted=Falsefordeltaind:
foropindelta:
ifop==elem:
is_contracted=Truebreakif (notis_contracted):
tmp.append(elem)
acc.append(tmp)
list_str=accifdebug:
forsign,d,sinzip(list_signs,list_deltas,list_str):
print(sign,d,s)
returnlist_signs, list_deltas, list_str
Combine deltas from one class
# The idea is to build the string by starting from the list of delta# From this list we can build a list of pairs of deltas that do not share the same idx# From this list of pairs of delta we can built a list of triplet of delta# and so on ...defcombine_one_class_delta(delta_i,i_op,string):
order_delta_i= []
iflen(delta_i) ==0:
returnorder_delta_iacc= []
iflen(delta_i) !=0:
fordindelta_i:
acc.append([d])
else:
acc.append([(0,0)])
order_delta_i.append(acc)
foriinrange(1,len(i_op)//2+1):
# List of termacc1= []
# a term = 1 or many delta that are multipliedlist_term=order_delta_i[i-1]
# list of delta of each term, 1 or many delta that are multipliedacc2= []
forlist_deltainlist_term:
list_op= []
# a single deltafordeltainlist_delta:
# the op that are contracted with the deltaforopindelta:
list_op.append(op)
# add delta, one on the existing delta and we look if we can do the contraction in# addition do the contractions already doneforadd_deltaindelta_i:
acc3=copy.deepcopy(list_delta)
idx_last=find_idx_elem(acc3[-1] ,delta_i)
idx_add=find_idx_elem(add_delta,delta_i)
ifidx_add<=idx_last:
continueis_in=False# check if the operator in the delta we want to add is already in another contractionforop1inadd_delta:
forop2inlist_op:
ifop1==op2:
is_in=Trueifis_in: continueifis_in: continueacc3.append(add_delta)
acc2.append(acc3)
#if there is no i-multiple delta iflen(acc2) ==0:
breakorder_delta_i.append(acc2)
# sign#for list_term in order_delta_i:# for list_delta in list_term:# sign = extract_sign(list_delta,string)returnorder_delta_i
Extract sign
# Product of two lists# To compute the sign based on a list of delta and the original string of operators defextract_sign(list_delta,string):
# position of the op in the different deltaslist_pos= []
fordeltainlist_delta:
tmp= []
foropindelta:
pos=find_idx_elem(op,string)
tmp.append(pos)
list_pos.append((tmp[0],tmp[1]))
# Number of crossing lines in the contractionsnb_cross=0forjinrange(0,len(list_pos)-1):
forkinrange(j+1,len(list_pos)):
pi_j=list_pos[j][0]
pf_j=list_pos[j][1]
pi_k=list_pos[k][0]
pf_k=list_pos[k][1]
# Crossing : ...pi_j ... pi_k ... pf_j ... pf_k...if (pf_k>pf_j) and (pi_k<pf_j) and (pi_k>pi_j) :
nb_cross=nb_cross+1# Number of permutation required to do the contractionnb_perm=0forposinlist_pos:
pi=pos[0]
pf=pos[1]
nb_perm=nb_perm+pf-pi-1# Final signsign= (-1)**nb_cross* (-1)**nb_permreturnsign
# extract a type of operator based on a pattern at the idxth position in string[:]defextract_op(string,pattern,idx,pos):
debug=False# Check typeiftype(string) !=type(['a','b']):
print('Type mismatch function extract_op arg 1')
sys.exit()
iftype(pattern) !=type('a'):
print('Type mismatch function extract_op arg 2')
sys.exit()
iftype(idx) !=type(1):
print('Type mismatch function extract_op arg 3')
sys.exit()
iftype(pos) !=type([1,2]):
print('Type mismatch function extract_op arg 4')
sys.exit()
# Debugifdebug: print('string:',string)
ifdebug: print('pattern:',pattern)
ifdebug: print('idx:',idx)
res= []
new_pos= []
i=0foreleminstring:
ifelem[idx] ==pattern:
res.append(elem)
new_pos.append(pos[i])
i=i+1returnres, new_pos
Build delta
# Build all the possible kronecker delta using 2 list of operators# and their position in the original string of operatordefbuild_delta(list_op1,list_op2,list_pos1,list_pos2):
debug=Falseidx_spin=3idx_act=4ifdebug: print('List op 1:',list_op1,'\List op 2:',list_op2)
ifdebug: print('List pos 1:',list_pos1,'\List pos 2:',list_pos2)
nb_idx=len(list_op1[0])
ifnb_idx<4ornb_idx>5:
print('The operators must have at least 4 indexes and maximum 5 indexes.')
sys.exit()
foreleminlist_op1:
iflen(elem) !=nb_idx:
print('All the operators must share the same number of indexes.')
sys.exit()
a1=''a2=' 'res= []
forop1, pos1inzip(list_op1,list_pos1):
s1=op1[idx_spin]
ifnb_idx==5:
a1=op1[idx_act]
forop2, pos2inzip(list_op2,list_pos2):
s2=op2[idx_spin]
ifnb_idx==5:
a2=op2[idx_act]
# if alpha-beta spinif (s1=='a'ands2=='b') or (s1=='b'ands2=='a'):
continue# if active-active contraction or not active-not active contractionifa1==a2andnb_idx>idx_act:
continueifpos2>pos1:
res.append([op1,op2])
ifdebug: print('Res:',res)
returnres
Find idx
# To search the index of an element in a listdeffind_idx_elem(elem,list_elem):
i=0fordinlist_elem:
ifd==elem:
breakelse:
i=i+1# checkifi==len(list_elem):
print('elem not found in find_idx_elem')
sys.exit()
returni
Reorder
# To put creation operator on the rightdefput_crea_to_left(sign,string):
acc= []
acc_pos= []
tmp= []
idx=2string_pos= [iforiinrange(len(string))]
forelem,posinzip(string,string_pos):
ifelem[idx] =='+':
acc.append(elem)
acc_pos.append(pos)
else:
tmp.append(elem)
order= [iforiinrange(len(acc))]
d=0forpi,pfinzip(acc_pos,order):
d=d+abs(pi-pf)
sign=pow(-1,d) *signforelemintmp:
acc.append(elem)
returnsign, acc
# 1: orbital class, i for occupied, a for unoccupied (for Fermi vacuum).# For the true vacuum, use a.# 2: orbital label# 3: operator type, + for creation, - for annihilation# 4: spin, a for $\alpha$, b for $\beta$, g for general (could be $\alpha$ or $\beta$)# 5: optional, to avoid contraction between some operators# (two operators with the same 5th index cannot be contracted together).if__name__=="__main__":
s= ['ip+g','aq-g','ir-g','is+g','at+g','iu-g']
#s = ['ix+g','iy+g','aw-g','av-g','iq+g','ip-g']#From this, we can call the function "do_wick" on s to apply# Wick's theorem and generate 3 lists, one for the signs, one# for the kronecker delta and one for the normal ordered string# containing the remaining uncontracted operators (WARNING:# the operators are not put in normal order in these strings,# but you can reorder them since it will only change the sign.# That's why we write them as $\{...\}_N$).list_sign, list_deltas, list_string=do_wick(s)
forsign,deltas,stringinzip(list_sign, list_deltas, list_string):
# Creates an object Wicked_str to print or display latex code obj=Wicked_str(sign,deltas,string)
# to print the each element of the result with latex formatobj.tex_show()
# to show the latex equation in a Jupyter Notebook#obj.eq_show()