दो कण इंटीग्रल <ij | kl> के लिए कुशल अनुक्रमण फ़ंक्शन को कैसे लागू किया जाए?


11

यह एक सरल समरूपता गणन समस्या है। मैं यहां पूरा बैकग्राउंड देता हूं, लेकिन क्वांटम केमिस्ट्री की कोई जानकारी नहीं है।

दो कण अभिन्न है: और इसमें निम्नलिखित 4 : मेरे पास एक फ़ंक्शन है जो अभिन्न की गणना करता है और उन्हें 1 डी सरणी में संग्रहीत करता है , निम्नानुसार अनुक्रमित:मैं जे | कश्मीर एल = ψ * मैं ( एक्स ) ψ * j ( एक्स ' ) ψ कश्मीर ( एक्स ) ψ एल ( एक्स ' )ij|klमैं जे | कश्मीर एल = जे मैं | एल कश्मीर = कश्मीर एल | मैं जे = एल कश्मीर | जे मैं

ij|kl=ψi(x)ψj(x)ψk(x)ψl(x)|xx|d3xd3x
ij|kl=ji|lk=kl|ij=lk|ji
int2
int2(ijkl2intindex2(i, j, k, l))

जहां फ़ंक्शन ijkl2intindex2एक अद्वितीय सूचकांक देता है, उपरोक्त समरूपताओं को ध्यान में रखता है। केवल आवश्यकता यह है कि यदि आप i, j, k, l (1 से n प्रत्येक से) के सभी संयोजनों पर लूप करते हैं, तो यह int2सरणी को लगातार भरेगा और यह सभी ijkl संयोजनों के लिए एक ही सूचकांक प्रदान करेगा जो उपरोक्त द्वारा संबंधित हैं 4 समरूपता।

फोरट्रान में मेरा वर्तमान कार्यान्वयन यहां है । यह बहुत धीमा है। किसी को पता है कि यह कैसे प्रभावी ढंग से करने के लिए? (किसी भी भाषा में)

संकेत: यदि ऑर्बिटल्स वास्तविक हैं, तो उपरोक्त अलावा, और आदान-प्रदान कर सकता है, इसलिए हमें कुल 8 मिलते हैं: और फिर कोई इसे अनुक्रमित करने के लिए एक बहुत तेज़ कार्य को कार्यान्वित कर सकता है, मेरा कार्यान्वयन यहाँ देखें । मैं उन मामलों के लिए कुछ कुशल अनुक्रमण योजना खोजना चाहता हूँ जब कक्षाएँ वास्तविक नहीं होती हैं।ψi(x)ikjl

ij|kl=ji|lk=kj|il=il|kj=
=kl|ij=lk|ji=il|kj=kj|il

नोट: जिन कार्यों को मैंने कार्यान्वित किया है, वे वास्तव में चार संख्याओं , , , को तथाकथित "रसायन शास्त्र" में स्वीकार करते हैं , , अर्थात और तर्कों का परस्पर संबंध है। लेकिन यह महत्वपूर्ण नहीं है।j कश्मीर एल ( मैं j | कश्मीर एल ) = मैं k | जे एल j कश्मीरijkl(ij|kl)=ik|jljk


ऑफ-टॉपिक, लेकिन क्या मैं नोटेशन द्वारा केवल एक ही व्यक्ति हूं ? इसे मार डालो, इसे आग से मार डालो! d3x
n00b

1
d3xdx1dx2dx3x=(x1,x2,x3)d3x

xx=(x1,x2,x3)dx

d3x

जवाबों:


5

[संपादित करें: चौथी बार आकर्षण, पिछले कुछ समझदार पर]

nn2(n2+3)t(t(n))+t(t(n1))t(a)at(a)=a(a+1)/2

ijtid(i,j)tid(k,l)tid(a,b)a,b

def ascendings(n):
    idx = 0
    for i in range(1,n+1):
        for j in range(1,i+1):
            for k in range(1,i):
                for l in range(1,k+1):
                    idx = idx + 1
                    print(i,j,k,l)
            k=i
            for l in range(1,j+1):
                idx = idx + 1
                print(i,j,k,l)
    return idx

llk

t(t(n1))

def mixcendings(n):
    idx = 0
    for j in range(2,n+1):
        for i in range(1,j):
            for k in range(1,j):
                for l in range(1,k):
                    print(i,j,k,l)
                    idx = idx + 1
            k=j
            for l in range(1,i+1):
                print(i,j,k,l)
                idx = idx + 1
    return idx

इन दोनों का संयोजन पूरा सेट देता है, इसलिए दोनों छोरों को एक साथ रखने से हमें सूचकांकों का पूरा सेट मिलता है।

n

अजगर में हम निम्नलिखित आइडेंट लिख सकते हैं कि हमें आइडीक्स दें और मैं, जे, के, एल प्रत्येक अलग-अलग परिदृश्यों के लिए मान:

def iterate_quad(n):
    idx = 0
    for i in range(1,n+1):
        for j in range(1,i+1):
            for k in range(1,i):
                for l in range(1,k+1):
                    idx = idx + 1
                    yield (idx,i,j,k,l)
                    #print(i,j,k,l)
            k=i
            for l in range(1,j+1):
                idx = idx + 1
                yield (idx,i,j,k,l)

    for i in range(2,n+1):
        for j in range(1,i):
            for k in range(1,i):
                for l in range(1,k):
                    idx = idx + 1
                    yield (idx,i,j,k,l)
            k=i
            for l in range(1,j+1):
                idx = idx + 1
                yield (idx,i,j,k,l)

in3+jn2+kn+l

integer function squareindex(i,j,k,l,n)
    integer,intent(in)::i,j,k,l,n
    squareindex = (((i-1)*n + (j-1))*n + (k-1))*n + l
end function

integer function generate_order_array(n,arr)
    integer,intent(in)::n,arr(*)
    integer::total,idx,i,j,k,l
    total = n**2 * (n**2 + 3)
    reshape(arr,total)
    idx = 0
    do i=1,n
      do j=1,i
        do k=1,i-1
          do l=1,k
            idx = idx+1
            arr(idx) = squareindex(i,j,k,l,n)
          end do
        end do
        k=i
        do l=1,j
          idx = idx+1
          arr(idx) = squareindex(i,j,k,l,n)
        end do
      end do
    end do

    do i=2,n
      do j=1,i-1
        do k=1,i-1
          do l=1,j
            idx = idx+1
            arr(idx) = squareindex(i,j,k,l,n)
          end do
        end do
        k=i
        do l=1,j
          idx = idx+1
          arr(idx) = squareindex(i,j,k,l,n)
        end do
      end do
    end do

    generate_order_array = idx
  end function

और फिर इस प्रकार लूप करें:

maxidx = generate_order_array(n,arr)
do idx=1,maxidx
  i = idx/(n**3) + 1
  t_idx = idx - (i-1)*n**3
  j = t_idx/(n**2) + 1
  t_idx = t_idx - (j-1)*n**2
  k = t_idx/n + 1
  t_idx = t_idx - (k-1)*n
  l = t_idx

  ! now have i,j,k,l, so do stuff
  ! ...
end do

हाय फिल, उत्तर के लिए बहुत बहुत धन्यवाद! मैंने इसका परीक्षण किया, और दो समस्याएं हैं। उदाहरण के लिए idx_all (1, 2, 3, 4, 4) == idx_all (1, 2, 4, 3, 4) = 76. लेकिन <12 | 34> / = <12 | 43>। यह तभी समान है जब कक्षाएँ वास्तविक हों। तो आपका समाधान 8 समरूपता के मामले के लिए प्रतीत होता है (मेरे फोरट्रान उदाहरण को सरल संस्करण के लिए देखें, ijkl2intindex ())। दूसरी समस्या यह है कि सूचकांक लगातार नहीं हैं, मैंने यहां परिणाम चिपकाए: gist.github.com/2703756 । यहाँ मेरे ijkl2intindex2 () दिनचर्या से ऊपर के सही परिणाम हैं: gist.github.com/2703767
ओन्डेज़ एज

1
@ Ond wantejČertík: आप एक साइन इन करना चाहते हैं? यदि आपने आदेश स्विच किया है तो idxpair को वापस लौटना होगा।
डेथब्रेथ

Ond Oejřertík: मैं अब अंतर देख रहा हूं। जैसा कि @Deathbreath बताते हैं, आप सूचकांक को नकार सकते हैं, लेकिन यह समग्र लूप के लिए उतना साफ नहीं होगा। मेरे पास एक सोच होगी और इसे अपडेट करूंगा।
फिल एच

दरअसल, इंडेक्स को नकारना पूरी तरह से काम नहीं करेगा क्योंकि आईडीएक्सपायर को मूल्य गलत मिलेगा।
फिल एच

<ij|kl>=<ji|kl>=<ij|lk>=<ji|lk>
ijkl[idxpair(indexij,indexkl,,)]signijsignkl

3

यहाँ समरूपता मामलों के लिए एक ही कुंजी को वापस करने के लिए एक सरल स्थान भरने वाले वक्र का उपयोग करने का विचार है (सभी कोड स्निपेट अजगर में हैं)।

# Simple space-filling curve
def forge_key(i, j, k, l, n): 
  return i + j*n + k*n**2 + l*n**3

# Considers the possible symmetries of a key
def forge_key_symmetry(i, j, k, l, n): 
  return min(forge_key(i, j, k, l, n), 
             forge_key(j, i, l, k, n), 
             forge_key(k, l, i, j, n), 
             forge_key(l, k, j, i, n)) 

टिप्पणियाँ:

  • उदाहरण अजगर है, लेकिन यदि आप अपने फोरट्रान कोड में कार्यों को इनलाइन करते हैं और (i, j, k, l) के लिए अपने आंतरिक लूप को अनियंत्रित करते हैं, तो आपको अच्छा प्रदर्शन मिलना चाहिए।
  • आप फ़्लोट्स का उपयोग करके कुंजी की गणना कर सकते हैं और फिर कुंजी को एक इंडेक्स के रूप में उपयोग करने के लिए पूर्णांक में परिवर्तित कर सकते हैं, इससे कंपाइलर को फ़्लोटिंग पॉइंट इकाइयों (उदाहरण के लिए एवीएक्स उपलब्ध है) का उपयोग करने की अनुमति मिलेगी।
  • यदि N 2 की शक्ति है, तो गुणन केवल थोड़ा बदलाव होगा।
  • समरूपता के लिए उपचार स्मृति में कुशल नहीं है (अर्थात यह एक सतत अनुक्रमण उत्पन्न नहीं करता है) और कुल सूचकांक सरणी प्रविष्टियों के 1/4 के आसपास उपयोग करता है।

यहाँ n = 2 के लिए एक परीक्षण उदाहरण दिया गया है:

for i in range(n):
  for j in range(n):
    for k in range(n):
      for l in range(n):
        key = forge_key_symmetry(i, j, k, l, n)
        print i, j, k , l, key

N = 2 के लिए आउटपुट:

i j k l key
0 0 0 0 0
0 0 0 1 1
0 0 1 0 1
0 0 1 1 3
0 1 0 0 1
0 1 0 1 5
0 1 1 0 6
0 1 1 1 7
1 0 0 0 1
1 0 0 1 6
1 0 1 0 5
1 0 1 1 7
1 1 0 0 3
1 1 0 1 7
1 1 1 0 7
1 1 1 1 15

यदि ब्याज, forge_key का उलटा कार्य है:

# Inverse of forge_key
def split_key(key, n): 
  d = key / n**3
  c = (key - d*n**3) / n**2
  b = (key - c*n**2 - d*n**3) / n 
  a = (key - b*n - c*n**2 - d*n**3)
  return (a, b, c, d)

क्या आपका मतलब था "अगर n 2 की शक्ति है" के बजाय 2 के कई है?
एरन अहमदिया

हाँ, धन्यवाद एरन। मैंने यह उत्तर रात के खाने के लिए जाने से पहले लिखा था और हल्क लिख रहा था।
fcruz

चतुर! हालाँकि, यदि आप 0 से शुरू करते हैं तो अधिकतम इंडेक्स n ^ 4 (या n ^ 4-1) नहीं है? समस्या यह है कि जिस आधार आकार के लिए मैं सक्षम होना चाहता हूं, वह स्मृति में फिट नहीं होगा। लगातार सूचकांक के साथ, सरणी का आकार n ^ 2 * (n ^ 2 + 3) / 4. Hm है, जो कि पूर्ण आकार के बारे में केवल 1/4 है। इसलिए शायद मुझे स्मृति खपत में 4 के कारक के बारे में चिंता नहीं करनी चाहिए। हालांकि, केवल 4 इन समरूपताओं (मेरी पोस्ट में मेरे बदसूरत समाधान की तुलना में बेहतर है, जहां मुझे डबल लूप करने की आवश्यकता है) का उपयोग करके सही निरंतर सूचकांक को एन्कोड करने का कोई तरीका होना चाहिए।
ओन्डेज़ एजर्ट

हाँ, यह सही है! मुझे नहीं पता कि कैसे सूचकांक को क्रमिक रूप से हल करना (पुन: क्रमबद्ध और पुन: व्यवस्थित किए बिना) करना है, लेकिन स्मृति उपयोग में अग्रणी शब्द ओ (एन ^ 4) है। 4 के कारक को बड़े एन के लिए स्मृति में थोड़ा अंतर करना चाहिए।
fcruz

0

क्या यह केवल पैक्ड सिमेट्रिक मैट्रिक्स इंडेक्सिंग समस्या का सामान्यीकरण नहीं है? वहाँ समाधान ऑफसेट (i, j) = i * (i + 1) / 2 + j है, है ना? क्या आप इस पर डबल-डाउन नहीं कर सकते हैं और दोहरे-सममित 4D सरणी को अनुक्रमित कर सकते हैं? ब्रांचिंग के लिए आवश्यक कार्यान्वयन अनावश्यक लगता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.