2012-11-26 35 views
7

जीएनयू सप्टक इस कोड में -हास्केल रेपा - सरणी को कैसे कम करें और सूचकांक लौटाएं?

[e, ix] = min(X); 

न्यूनतम तत्व वापस आ जाएगी और यह स्थान है। मनमाने ढंग से बाइनरी फ़ंक्शन के लिए रेपा में आप यह कैसे करते हैं? पुनरावृत्तियों की गणना के लिए एक (झ - हम दो एक्युमुलेटरों साथ (Data.List से) 'repa -1 डी मैट्रिक्स कन्वर्ट सूची और foldl उपयोग करने के लिए

min x = z $ foldl' f (e,0,0) es 
    where 
    (e:es) = toList x 
    f (a,ix,r) b = let ix' = ix+1 in if a < b then (a,ix',r) else (b,ix',ix') 
    z (a,ix,r) = (a,r) 

ऊपर के उदाहरण में:

यह है कि मैं क्या लेकर आए हैं) और अन्य न्यूनतम तत्व (आर) की स्थिति को बचाने के लिए। लेकिन रेपा का उपयोग करने का पूरा बिंदु सरणी का उपयोग करना है, सूची नहीं!

रेपा में ऐरे प्रकार (फ़ोल्ड्स और फोल्डपी) के लिए दो गुना हैं - लेकिन वे केवल प्रकार (ए -> ए -> ए) का कार्य ले सकते हैं - यानी, मैं इसे जमाकर्ताओं के साथ ट्यूपल पास नहीं कर सकता। ,

min x = traverse x to0D min 
    where 
    to0D (Z:.i) = Z 
    min f (Z) = ??? -- how to get elements for comparison? 

पहली बात यह है कि मन में आता है

[f (Z:.i) | i <- [1..n]], where n = (\(Z:.i) -> i) $ extent x 

है लेकिन यह भी सरणी सूची में परिवर्तित कर देंगे: वहाँ भी पार है, जो, सिद्धांत रूप में, एक अदिश सरणी के लिए 1 डी सरणी कम कर सकते हैं सरणी पर गणना करने के बजाय।

+2

वास्तव में रेपा से परिचित नहीं है, लेकिन क्या आप 'foldP?' का उपयोग करने से पहले प्रत्येक आइटम को टुपल पर मानचित्रित नहीं कर सकते हैं। उदाहरण के लिए, आप न्यूनतम तत्व के टुपल, न्यूनतम की अनुक्रमणिका और सबएरे की लंबाई का उपयोग करके एक उपैरे का वर्णन कर सकते हैं। तो आप प्रत्येक तत्व 'x' से '(x, 0, 1)' और फिर 'f (x, i, n) (y, j, m) = का उपयोग करते हुए समांतर गुना मैप करते हैं = यदि x hammar

+0

क्षमा करें, यह निश्चित रूप से 'maxBound' होना चाहिए। – hammar

+0

एक tuple के साथ foldP का उपयोग करने के लिए आपको उन tuples के साथ सरणी होगी। यह किया जा सकता है, लेकिन यह छवि प्रसंस्करण (लाखों तत्वों) के लिए अपर्याप्त है। – EvgenijM86

उत्तर

3

मैं रिपा पर कोई विशेषज्ञ नहीं हूं, लेकिन ऐसा लगता है कि यह 1-डी सरणी के लिए काम करता है। इसे शायद अन्य आयामों के लिए अनुकूलित किया जा सकता है।

import Data.Array.Repa 

indexed arr = traverse arr id (\src [email protected](Z :. i) -> (src idx, i)) 

minimize arr = foldP f h t 
    where 
    (Z :. n) = extent arr 
    arr' = indexed arr 
    h = arr' ! (Z :. 0) 
    t = extract (Z :. 1) (Z :. (n-1)) arr' 
    f [email protected](valMin, iMin) [email protected](val, i) | val < valMin = x 
            | otherwise = min 
+0

मुझे एक ही समस्या का सामना करना पड़ रहा है और कोई अन्य समाधान नहीं मिला। – olek

0

एक ज़ोंबी पद को पुनर्जीवित करने के जोखिम पर, यहाँ एक मनमाना आयाम समाधान मैं बाहर काम किया (जो, टिप्पणियों की समीक्षा, वास्तव में क्या सुझाव दिया @hammar है)। foldAllP की अजीब प्रकृति की वजह से, जिसे मैं ट्यूपल्स विलय करते समय पहचान तत्व के रूप में उपयोग करता हूं, आपको उस सरणी के न्यूनतम ऊपरी बाउंड को भी प्रदान करने की आवश्यकता होती है जिसे आप ढूंढना चाहते हैं।

import Data.Array.Repa 
import Data.Array.Repa.Eval 
import Data.Array.Repa.Repr.Unboxed 

minimize :: (Shape sh, Source r a, Elt a, Unbox a, Monad m, Ord a) => Array r sh a -> a -> m (a,sh) 
minimize arr upperBound = do 
     -- Zip the array with its (Int representation of) indices 
     let zippedWithIndex = Data.Array.Repa.traverse arr id (\f idx -> (f idx, toIndex (extent arr) idx)) 

     -- Define a function that compares two tuple of (a,Int) on the value of the first entry 
     let minimumIndex [email protected](v,_) t'@(v',_) = if v < v' then t else t' 

     -- Do a parallel fold of all elements in the array 
     (min,idx) <- foldAllP minimumIndex (upperBound, error "Empty array") zippedWithIndex 

     -- convert the indice back from its Int representation 
     return (min, fromIndex (extent arr) idx) 

स्वाभाविक रूप से, अगर आपके सरणी एक प्रकार Bounded का एक उदाहरण है कि होता है, तो आप और अधिक सुविधाजनक समारोह

minimize' arr = minimize arr maxBound 

कर सकते हैं कुछ परीक्षण आप प्रॉम्प्ट पर कर सकते हैं:

λ> let x = fromListUnboxed (ix2 2 2) [20, 30, 10, 40] :: Array U DIM2 Int 
λ> minimize' x 
(10,(Z :. 1) :. 0)