2012-06-11 9 views
14

मैं अपने कार्यक्रम में रैखिक बीजगणित इंजन के रूप में ईजिन मैट्रिक्स लाइब्रेरी का उपयोग करना चाहता हूं। आइजीन आलसी मूल्यांकन को लागू करने और लूप और गणना को सरल बनाने के लिए अभिव्यक्ति टेम्पलेट का उपयोग करता है।अभिव्यक्ति टेम्पलेट का उपयोग करने वाली लाइब्रेरी को एकीकृत कैसे करें?

उदाहरण के लिए:

#include<Eigen/Core> 

int main() 
{ 
    int size = 40; 
    // VectorXf is a vector of floats, with dynamic size. 
    Eigen::VectorXf u(size), v(size), w(size), z(size); 
    u = 2*v + w + 0.2*z; 
} 

के बाद से Eigen अभिव्यक्ति टेम्पलेट्स, कोड का उपयोग करता है की तरह

u = 2*v + w + 0.2*z; 

ऊपर उल्लेख नमूने में लंबाई 10 (नहीं 40 की एक एकल पाश को कम कर देता है, तैरता डाल रहे हैं अस्थायी बनाने के बिना 4 के टुकड़ों द्वारा regiser में)। कितना मजेदार था वो?

लेकिन अगर मैं इस तरह पुस्तकालय एकीकृत:

class UsingEigen 
{ 
    public: 
     UsingEigen(const Eigen::VectorXf& data): 
      data_(data) 
     {} 

     UsingEigen operator + (const UsingEigen& adee)const 
     { 
      return UsingEigen(data_ + adee.data_); 
     } 

     ... 
    private: 
     Eigen::VectorXf data_; 
} 

तो जैसे भाव:

UsingEigen a, b, c, d; 
a = b + c + d; 

रास्ता Eigen कार्यान्वित किया जाता है का लाभ नहीं ले सकते। और यह आखिरी नहीं है। कई अन्य उदाहरण हैं, जहां ईजिन में अभिव्यक्ति टेम्पलेट का उपयोग किया जाता है।

आसान उपाय, अपने आप से ऑपरेटरों को परिभाषित data_ सार्वजनिक करने और जैसे भाव लिखने के लिए नहीं होगा:

UsingEigen a, b, c, d; 
a.data_ = b.data_ + c.data_ + d.data_; 

यह कैप्सूलीकरण टूट जाता है, लेकिन यह Eigen की दक्षता बरकरार रखता है।

अन्य तरीकों से मेरे अपने ऑपरेटरों को बनाने के लिए हो सकता है, लेकिन उन्हें अभिव्यक्ति टेम्पलेट्स लौटाने दें। लेकिन चूंकि मैं सी ++ में एक नौसिखिया हूं, मुझे नहीं पता कि यह जाने का सही तरीका है या नहीं।

मुझे खेद है कि प्रश्न प्रकृति में बहुत सामान्य है। मैं एक नौसिखिया हूं और पूछने के लिए कोई नहीं है। अब तक मैं हर जगह std::vector<float> का उपयोग कर रहा था, लेकिन अब मुझे मैट्रिक्स का उपयोग करने की आवश्यकता है। मेरी पूरी परियोजना में std::vector<float> से ईजिन तक स्विच करने के लिए एक बड़ा कदम है और मुझे शुरुआत में गलत कॉल करने से डर है। किसी भी सलाह का स्वागत है!

+1

दिलचस्प समस्या। पहली बात यह है कि, आप इस तरह से ईजिन लाइब्रेरी वैक्टरों को क्यों समाहित करना चाहते हैं? आपके वर्ग क्या व्यवहार करते हैं? –

+0

मेरी कक्षाएं ईजिन लाइब्रेरी कक्षाओं में स्वयं को कोई कार्यक्षमता नहीं जोड़ती हैं, लेकिन उनका उपयोग करें। उदाहरण के लिए मेरे कोर वर्गों में से एक दो वैक्टर स्टोर करता है। एक निश्चित गणितीय गणना के लिए एक इनपुट के रूप में और दूसरा आउटपुट के रूप में। जैसा कि मैंने उपर्युक्त उल्लेख किया है, इन वस्तुओं को एक समान तरीके से अंतःक्रिया करने की आवश्यकता है। जब आप दो ऐसी वस्तुएं जोड़ते हैं, तो इनपुट जोड़ना चाहिए। –

+1

मुझे नहीं लगता कि अभिव्यक्ति टेम्पलेट ढांचे के अपने हिस्से को पुन: उत्पन्न किए बिना यह संभव है। उदाहरण के लिए, '(ए + बी) * सी' कुछ' ExprCwiseAdd * UsingEigen' जैसा होगा (नाम बनाया गया है, इसे अब याद नहीं है), और वहां कहीं भी परिभाषित 'ExprCwiseAdd * UseEigen' होना होगा) , लेकिन 'ExprCwiseAdd * ExprCWiseAdd' और इसी तरह भी। संक्षेप में, अतिरिक्त में 'UseEigen' रिटर्न प्रकार के रूप में नहीं होगा। (आप [बूस्ट :: प्रोटो] (http://www.boost.org/doc/libs/1_49_0/doc/html/proto.html) पर एक नज़र डाल सकते हैं जो अभिव्यक्ति टेम्पलेट्स के लिए एक ढांचा है)। सौभाग्य। – eudoxos

उत्तर

4

data_ ब्रेक इंकापुलेशन का खुलासा क्यों करेगा? Encapsulation का मतलब है कार्यान्वयन विवरण छुपाएं और केवल इंटरफ़ेस को उजागर करना। यदि आपका रैपर वर्ग UsingEigen मूल Eigen लाइब्रेरी में कोई व्यवहार या स्थिति नहीं जोड़ता है, तो इंटरफ़ेस नहीं बदलता है। इस मामले में, आपको इस रैपर को पूरी तरह से छोड़ना चाहिए और Eigen डेटा संरचनाओं का उपयोग करके अपना प्रोग्राम लिखना चाहिए।

मैट्रिक्स या वेक्टर का खुलासा करना encapsulation नहीं तोड़ रहा है: केवल मैट्रिक्स या वेक्टर के कार्यान्वयन को उजागर करना होगा। Eigen पुस्तकालय अंकगणितीय ऑपरेटरों का खुलासा करता है लेकिन उनके कार्यान्वयन नहीं।

अभिव्यक्ति टेम्पलेट पुस्तकालयों के साथ, लाइब्रेरी कार्यक्षमता का विस्तार करने के लिए उपयोगकर्ताओं का सबसे आम तरीका व्यवहार जोड़कर, राज्य जोड़कर जोड़ना नहीं है। और व्यवहार जोड़ने के लिए आपको रैपर कक्षाएं लिखने की आवश्यकता नहीं है: आप Eigen कक्षा सदस्य कार्यों के संदर्भ में लागू गैर-सदस्य फ़ंक्शंस भी जोड़ सकते हैं। स्कॉट मेयर्स द्वारा this column "गैर-सदस्य फ़ंक्शंस एनकैप्यूलेशन कैसे सुधारते हैं" देखें।

आपकी चिंता के लिए कि आपके वर्तमान प्रोग्राम का एक संस्करण में परिवर्तन जो स्पष्ट रूप से Eigen कार्यक्षमता का उपयोग करता है: आप प्रत्येक बार अपने प्रोग्राम के छोटे हिस्सों को बदलने, चरण-दर-चरण परिवर्तन कर सकते हैं, यह सुनिश्चित कर सकते हैं कि आपका यूनिट परीक्षण (आपके पास यूनिट परीक्षण हैं, है ना?) जैसे ही आप साथ जाते हैं तो ब्रेक न करें।

+2

* डेटा सदस्यों का खुलासा * encapsulation तोड़ता है। लेकिन ईजिन वर्गों के लिए अभिव्यक्ति टेम्पलेट्स ओवरलोड को जोड़कर इसे उसी तरह तोड़ दिया जाएगा। –

+0

@ कोनराड्रूडॉल्फ यह 'encEigen' का सटीक समान इंटरफ़ेस है और सटीक उसी कार्यान्वयन के साथ encaculation तोड़ता नहीं है (यानी शुद्ध अग्रेषण के साथ एक शाब्दिक रैपर वर्ग और कोई लॉगिंग/जांच आदि शामिल नहीं है)। आप सही होंगे अगर 'ईइजिन' अबास्ट्रक्शन की एक अतिरिक्त परत को परिभाषित करेगा, लेकिन यह मामला प्रतीत नहीं होता है (और इसे तब भी 'प्रयोग करना' कहा नहीं जाना चाहिए क्योंकि यह कार्यान्वयन का खुलासा करता है!) – TemplateRex

-2

मुझे आपके सभी प्रश्नों को समझ में नहीं आ रहा है, मैं उनमें से अधिकांश का जवाब देने की कोशिश करूंगा। इस वाक्य में:

UsingEigen operator + (const UsingEigen& adee)const 
    { 
     return UsingEigen(data_ + adee.data_); 
    } 

आप एक अधिभार ऑपरेटर (खेद मैं अगर यह अंग्रेजी में लिखने के लिए सही तरीका क्या है पता नहीं है) है, इस कारण के लिए आप लिख सकते हैं:

a = b + c + d; 

इसके बजाय:

a.data_ = b.data_ + c.data_ + d.data_; 

आपको कोई समस्या नहीं होगी, आपके कार्यक्रम की लागत समान होगी। इसके अलावा आप encapsulation और दक्षता होगी।

दूसरी तरफ यदि आप अपना ऑपरेटर परिभाषित करना चाहते हैं तो आप इसे टेम्पलेट की तरह कर सकते हैं। आप वेब की खोज "अधिभार ऑपरेटर" लेकिन इस के समान है के बारे में जानकारी पा सकते हैं:

UsingEigen operator + (const UsingEigen& adee)const 
    { 
     return UsingEigen(data_ + adee.data_); 
    } 
बजाय

"+" आप ऑपरेटर डाल दिया और संचालन की जरूरत कर सकते हैं।

यदि आप एक मैट्रिक्स बनाना चाहते हैं तो यह आसान है। आपको केवल वेक्टर की सरणी या वेक्टर की सरणी बनाने की आवश्यकता है।

मुझे लगता है कि कुछ इस तरह है:

std::vector<vector<float>> 

मुझे यकीन है कि नहीं कर रहा हूँ, लेकिन यह आसान है, दूसरी ओर अगर आप इस तरह पर एक साधारण मैट्रिक्स का उपयोग कर सकते हैं:

नाव YourMatrix [आकार] [आकार];

मुझे उम्मीद है कि यह आपकी मदद कर सकता है। अगर आपको कुछ और चाहिए तो मुझे Google + पर जोड़ने की ज़रूरत है और मैं आपकी मदद करने की कोशिश करूंगा।

मेरी अंग्रेजी के लिए खेद है, मुझे उम्मीद है कि आप सभी को समझ सकते हैं और यह आपकी मदद करता है।

+1

दुर्भाग्यवश, आप गलत हैं। आपको [अभिव्यक्ति टेम्पलेट्स] (http://en.wikipedia.org/wiki/Expression_templates) पर पढ़ने की आवश्यकता है और वे इस कोड को कैसे प्रभावित करते हैं। आपके अधिभारित ऑपरेटर अभिव्यक्ति टेम्पलेट का लाभ नहीं उठाएंगे, ठीक उसी तरह जैसा ओपी ने वर्णित किया है। इसके अलावा, ईजिन पुस्तकालय आपके द्वारा दिखाए गए बेवकूफ नेस्टेड-सरणी दृष्टिकोण से अधिक अर्थशास्त्र प्रदान करता है, जो ओपी के लिए पूरी तरह से अपर्याप्त है। –

+0

मैनुअल धन्यवाद, अगर मैं आपके दृष्टिकोण का उपयोग करता हूं, तो प्रोग्राम संकलित और सही तरीके से काम करेगा। लेकिन एक = बी + सी + डी की तरह अभिव्यक्तियां; इसके परिणामस्वरूप कुछ ऐसा होगा: पहले बी + सी की गणना अस्थायी बीसीटीएमपी में की जाएगी और संग्रहीत की जाएगी। फिर bctemp डी में जोड़ा जाएगा और bcdtemp बनाएँ। अंत में, bcdtemp को असाइन किया जाएगा। वह 3 लूप और 2 अस्थायी हैं। मेरा लक्ष्य इस से बचना है। –

+0

@ मैनुअल यदि आप अस्थायी और लूप से बचकर मेरा क्या मतलब रखते हैं, तो आप यहां बेहतर स्पष्टीकरण पा सकते हैं http://eigen.tuxfamily.org/dox/TopicInsideEigenExample.html –

2

मेरी राय में, यह लाइब्रेरी उपयोग की समस्या के बजाय ऑब्जेक्ट उन्मुख डिज़ाइन समस्या का अधिक दिखता है। जो कुछ भी आप किताबों से पढ़ते हैं वह सही सिफारिशें हैं। यानी, सदस्य चर का पर्दाफाश न करें और ऊपरी परतों को तीसरे पक्ष के परत उपयोग की बारीकियों से ढाल दें।

आप जो भी देख सकते हैं वह गणितीय कार्यों के सही सार तत्व हैं जिन्हें आंतरिक रूप से इस पुस्तकालय का उपयोग करके कार्यान्वित किया जा सकता है। यानी, आप प्राथमिक वेक्टर और मैट्रिक्स संचालन की तुलना में उच्च स्तर के कार्यों के साथ अपनी खुद की एक पुस्तकालय का पर्दाफाश कर सकते हैं। इस तरह आप लाइब्रेरी ऑब्जेक्ट्स के बीच इंटरैक्शन की विशिष्टताओं का उपयोग कर सकते हैं और साथ ही आपको ऊपरी परतों पर अपने सदस्य चर का पर्दाफाश करने की आवश्यकता नहीं है।

उदाहरण के लिए आप मेरे उच्च स्तरीय एपीआई को दूर कर सकते हैं जैसे कि एक बिंदु से एक विमान तक दूरी की गणना करना, दो विमानों के बीच की दूरी, एक बिंदु के नए निर्देशांक की गणना करना, रूपांतरण मैट्रिक्स आदि का उपयोग करके एक और समन्वय प्रणाली लिखना आदि। इन्हें लागू करने के लिए आंतरिक रूप से विधियों आप पुस्तकालय वस्तुओं का उपयोग कर सकते हैं।इस लाइब्रेरी पर ऊपरी परतों के लिए निर्भरता से बचने के लिए आप API हस्ताक्षर में उपयोग की जाने वाली किसी भी लाइब्रेरी कक्षाओं को न रखने के लिए प्रतिबंधित कर सकते हैं।

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

संबंधित मुद्दे