में आलसी संकल्प एफएन के साथ परेशानी मैं कुछ सिग्नल प्रोसेसिंग सॉफ्टवेयर लिख रहा हूं, और मैं discrete convolution function लिखकर शुरू कर रहा हूं।क्लोजर
यह पहले दस हजार या तो मूल्यों की सूची के लिए ठीक काम करता है, लेकिन जैसे ही वे बड़े होते हैं (कहें, 100k), मुझे निश्चित रूप से स्टैक ओवरफ्लो त्रुटियां मिलनी शुरू होती हैं।
दुर्भाग्य से, मैं एक पुनरावर्ती & आलसी संस्करण है कि वास्तव में काफी तेजी से (लालित्य के कम से कम थोड़ी रूप में अच्छी तरह अच्छा होगा होने का उपयोग करने के लिए आवश्यक घुमाव के एल्गोरिथ्म मैं परिवर्तित मुसीबत का एक बहुत हो रहा है)।
मैं भी 100% सुनिश्चित नहीं हूं कि मेरे पास यह कार्य पूरी तरह से सही है, फिर भी – कृपया मुझे बताएं कि क्या मुझे कुछ गड़बड़ है या कुछ गलत कर रहा है। मैं सोचता हूं यह सही है।
(defn convolve
"
Convolves xs with is.
This is a discrete convolution.
'xs :: list of numbers
'is :: list of numbers
"
[xs is]
(loop [xs xs finalacc() acc()]
(if (empty? xs)
(concat finalacc acc)
(recur (rest xs)
(if (empty? acc)
()
(concat finalacc [(first acc)]))
(if (empty? acc)
(map #(* (first xs) %) is)
(vec-add
(map #(* (first xs) %) is)
(rest acc)))))))
मैं ज्यादा मदद की किसी भी प्रकार के लिए बाध्य नहीं किया था: मैं अभी भी Clojure में मेरी बीयरिंग हो रही है, और इस खूबसूरत और आलसी बना रही है और/या पुनरावर्ती अद्भुत होगा।
मुझे आश्चर्य है कि एक एल्गोरिदम व्यक्त करना कितना मुश्किल है जो लिस्प में एक अनिवार्य भाषा में व्यक्त करना आसान है। लेकिन शायद मैं यह गलत कर रहा हूँ!
संपादित करें: बस दिखाने के लिए कितना आसान है एक अनिवार्य भाषा में व्यक्त करने के लिए है, और लोगों को एल्गोरिथ्म है कि अच्छी तरह से काम करता है और पढ़ने में आसान है, यहाँ अजगर संस्करण है देने के लिए। कम, संक्षिप्त और अधिक आसान होने के कारण, यह क्लोजर कोड की तुलना में तीव्रता के आदेश निष्पादित करता है: जावा सरणी का उपयोग करके मेरा अनिवार्य क्लोजर कोड भी।
from itertools import repeat
def convolve(ns, ms):
y = [i for i in repeat(0, len(ns)+len(ms)-1)]
for n in range(len(ns)):
for m in range(len(ms)):
y[n+m] = y[n+m] + ns[n]*ms[m]
return y
दूसरी ओर, अनिवार्य क्लोजर कोड है। यह अंतिम, गैर पूरी तरह से विसर्जित, संकल्प से मूल्य भी छोड़ देता है। तो धीमी और बदसूरत होने से अलग, यह 100% कार्यात्मक नहीं है। न ही कार्यात्मक।
(defn imp-convolve-1
[xs is]
(let [ys (into-array Double (repeat (dec (+ (count xs) (count is))) 0.0))
xs (vec xs)
is (vec is)]
(map #(first %)
(for [i (range (count xs))]
(for [j (range (count is))]
(aset ys (+ i j)
(+ (* (nth xs i) (nth is j))
(nth ys (+ i j)))))))))
यह बहुत निराशाजनक है। कृपया, कोई मुझे दिखाता है कि मैंने अभी कुछ स्पष्ट याद किया है।
संपादित करें 3:
यहाँ एक और संस्करण मैं कल सोचा है, दिखा कैसे मैं (हालांकि अन्य समाधान काफी सुंदर हैं इसे व्यक्त सक्षम होना चाहते हैं, मैं बस वहाँ बाहर एक और एक डाल रहा हूँ!
(defn vec-add
([xs] (vec-add xs []))
([xs ys]
(let [lxs (count xs)
lys (count ys)
xs (pad-r xs lys)
ys (pad-r ys lxs)]
(vec (map #(+ %1 %2) xs ys))))
([xs ys & more]
(vec (reduce vec-add (vec-add xs ys) more))))
(vec (reduce vec-add (vec-add xs ys) more))))
यह आपके सवाल का एक जवाब सभी पर नहीं है, लेकिन ... फास्ट फूरियर Transforms का उपयोग करके घुमाव को लागू करने में काफी आपरेशन की संख्या कम कर देता है (http://stackoverflow.com/questions/3084987/low- देखना उदाहरण के लिए, पास-फ़िल्टर-उपयोग-एफएफटी-बदले में-रूपांतरण-कार्यान्वयन)। – mtrw
मुझे यह जानने के लिए कार्यात्मक भाषाओं के बारे में पर्याप्त जानकारी नहीं है कि यह मदद करेगा, लेकिन आपको http://stackoverflow.com/questions/803055/how-do-i-do-convolution-in-f में रुचि हो सकती है। – mtrw
@mtrw उत्पादन में, यह निश्चित रूप से एफएफटी का उपयोग करके किया जाएगा; अभी के लिए, हालांकि, मुझे एक अच्छा, कार्यात्मक, समाधान होना अच्छा लगेगा। लेकिन मुझे यकीन नहीं है कि यह कितना संभव है (क्लोजर में)। – Isaac