2016-02-18 35 views
7

को सूचीबद्ध करने में समय जटिलता जब एक numpy सरणी होने मुझे लगता है, मान लें किक्या एक numpy सरणी सीधे

>>>>nArray 
array([[ 23425.  , 521331.40625], 
     [ 23465.  , 521246.03125], 
     [ 23505.  , 528602.8125 ], 
     [ 23545.  , 531934.75 ], 
     [ 23585.  , 534916.375 ], 
     [ 23865.  , 527971.1875 ]]) 

प्रत्यक्ष अनुक्रमण बहुत कुशल होना चाहिए करते हैं।

मुझे लगता है कि nArray[0, 1] = 69696420 जैसे कुछ हैश-टेबल का उपयोग करना चाहिए जो ओ (1) के करीब एक समय जटिलता प्रदान करेगा। क्या वह सही है?

अद्यतन

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

अपडेट 2

मैं जवाब

+0

"प्रत्यक्ष अनुक्रमण बहुत कुशल होना चाहिए" - यह इस बात पर निर्भर करता है कि आप वास्तव में "कुशल" से क्या मतलब रखते हैं। बड़े-ओ शब्दों में आप स्पष्ट रूप से * ओ (1) * से बेहतर नहीं कर सकते हैं, लेकिन यह निरंतर कारक के आकार को अनदेखा करता है। जैसा कि @AmiTavory ने सही ढंग से इंगित किया है, हालांकि, अनुक्रमण में पाइथन फ़ंक्शन कॉल शामिल हैं, जो निम्न-स्तरीय भाषाओं में उन लोगों की तुलना में अधिक महंगे हैं। –

उत्तर

5

एक ओर

एक हैश तालिका जो एक समय जटिलता पास दे देंगे का उपयोग करना होगा ओ (1) के लिए। क्या वह सही है?

बिल्कुल सही नहीं है। Numpy array एस मूल रूप से contiguous blocks of homogeneous memory हैं, आयामों और इस तरह के पक्ष में कुछ अतिरिक्त जानकारी के साथ। इसलिए, पहुंच ओ (1) है, और स्मृति में स्थिति निर्धारित करने के लिए बस कुछ मामूली गणित शामिल है।

दूसरी ओर

अनुक्रमण पर बहुत कुशल होना चाहिए।

दुर्भाग्यवश बिल्कुल सही नहीं है। सीमाओं की जांच (जो सरणी करते हैं) से सहायक, शुद्ध पायथन से जुड़ी सब कुछ बेहद अक्षम है (और इसमें शुद्ध-पायथन कॉल शामिल हैं)। Numpy सरणी का उपयोग no exception है। जब भी संभव हो, आपको वेक्टर परिचालनों का उपयोग करने की कोशिश करनी चाहिए।

+0

मुझे प्रत्यक्ष अनुक्रमण कहना चाहिए, जिसका अर्थ है कि जब आप उस 'nArray [0, 0]' जैसे कुछ निर्दिष्ट करते हैं। – LetsPlayYahtzee

+1

डायरेक्ट इंडेक्सिंग फ़ंक्शन कॉल के लिए सिंटैक्टिक चीनी है, अनिवार्य रूप से। –

+0

लेकिन, हैशिंग के बारे में गलत विचार को ध्यान में रखते हुए, सीधे एक numpy सरणी अनुक्रमणित करना बहुत कुशल नहीं है? – LetsPlayYahtzee

3

कोई हैश शामिल टेबल है की वैधता साबित करने के लिए एक सरल बेंच मार्किंग गयी। NumPy सरणी, सरणियों हैं ठीक वैसे ही जैसा कि नाम से स्पष्ट है, और पता इस तरह की जाती है:

address of nArray[x, y] = base address + A * x + B * y 
+0

आप सही हैं, वहां हैश-टेबल की आवश्यकता नहीं है, इसलिए समय जटिलता वास्तव में स्थिर है – LetsPlayYahtzee

1

अमी के उत्तर के परीक्षण के माध्यम से कुछ अतिरिक्त सत्यापन जोड़ने के लिए मैंने एक सरल सर्कुलर बफर बनाया जो एक संख्यात्मक सरणी से है जो केवल प्रविष्टि बनाने के लिए प्रत्यक्ष अनुक्रमण का उपयोग करता है। असल में प्रत्येक सम्मिलन कतार में सबसे पुराने तत्व के मानों को बदलता है।

कोड पूरी तरह से बग मुक्त नहीं है लेकिन यह कुछ सरल प्रदर्शन बेंचमार्किंग के आधार के रूप में कार्य कर सकता है।

import math 
import numpy as np 


class CircFifo(): 
""" 
helper class, uses a numpy array to provide a circular fixed size fifo 
interface. 

put(element): removes the oldest element and 
places a new one 

get(): returns the oldest entry 

empty(): returns true if fifo is empty 

full(): returns true if fifo is full 
""" 
def __init__(self, size): 
    self.array = np.empty(shape=(size, 2)) 
    self.size = size 
    self.array[:] = np.NAN 
    self.top = 0 
    self.bottom = 0 

def put(self, row): 
    self.array[self.top, :] = row 
    self.top += 1 
    if self.top == self.size: 
     self.top = 0 

def get(self): 
    if not math.isnan(self.array[self.bottom, 0]): 
     row = copy.deepcopy(self.array[self.bottom, :]) 
     self.array[self.bottom, :] = float('NaN') 
     self.bottom += 1 
    if self.bottom == self.size: 
     self.bottom = 0 
    if math.isnan(self.array[self.bottom, 0]): 
     self.bottom = 0 
     self.top = 0 
    return row 

def empty(self): 
    if math.isnan(self.array[self.bottom, 0]): 
     return True 
    else: 
     return False 

def full(self): 
    if self.size - np.count_nonzero(
      np.isnan(self.array[:, 0])) == self.size: 
     return True 
    else: 
     return False 

पद में उत्तरों की शुद्धता की पुष्टि एक साधारण परीक्षण के माध्यम से की जाती है। मैंने एक डेक ऑब्जेक्ट के खिलाफ सम्मिलन प्रदर्शन का परीक्षण किया। यहां तक ​​कि 1000 सम्मिलन डेक के लिए, जो एक गतिशील और स्थैतिक डेटा संरचना (मेरे स्थिर सर्कुलर फीफो के विपरीत) के रूप में सर्वर भी है, स्पष्ट रूप से परिपत्र फीफो से बेहतर प्रदर्शन करता है।

यहाँ साधारण परीक्षण मैं

In [5]: import time 

In [6]: circFifo = CircFifo(300) 

In [7]: elapsedTime = 0 

In [8]: for i in range(1, 1000): 
    ...:   start = time.time() 
    ...:   circFifo.put(np.array([[52, 12]])) 
    ...:   elapsedTime += time.time() - start 
    ...:  

In [9]: elapsedTime 
Out[9]: 0.010616540908813477 


In [21]: queue = deque() 

In [22]: elapsedTime = 0 

In [23]: for i in range(1, 1000): 
    ....:   start = time.time() 
    ....:   queue.append(np.array([[52, 12]])) 
    ....:   elapsedTime += time.time() - start 
    ....:  

In [24]: elapsedTime 
Out[24]: 0.00482630729675293 

चलाने मुझे पता है कि इस बेंचमार्क कि जानकारीपूर्ण नहीं है, लेकिन यह काफी स्पष्ट हो जाता है कि Deque बहुत तेजी से होता है। कम से कम उस प्रविष्टि के लिए।

मैं उम्मीद करता हूं कि यदि उस परिपत्र फीफो को सी में एक स्थिर सरणी के साथ कार्यान्वित किया गया था तो इसे आसानी से बेहतर नहीं किया जा सका। चूंकि मूल रूप से सी की स्थिर सरणी सबसे सरल है और कम ओवरहेड डेटा संरचना उपलब्ध है।

+1

मुझे वापस '%% टाइमिट 'के अस्तित्व के बारे में पता नहीं था – LetsPlayYahtzee