2009-01-07 12 views
21

मैं ऐसे x^2+y^2 के रूप में कुछ भाव है कि मैं कुछ गणित की गणना के लिए उपयोग करना चाहते हैं की है। उन चीजों में से एक जो मैं करना चाहता हूं वह अभिव्यक्ति के आंशिक डेरिवेटिव लेना है।सी/सी ++ में डेरिवेटिव्स?

तो अगर f(x,y) = x^2 + y^2 तो x के संबंध में f का आंशिक y को 2x, आंशिक होगा सम्मान के साथ 2y होगा।

मैंने एक सीमित अंतर विधि का उपयोग करके एक बदबूदार समारोह लिखा लेकिन मैं फ्लोटिंग पॉइंट परिशुद्धता के साथ कई समस्याओं में भाग रहा हूं। उदाहरण के लिए, मैं 1.99234 बजाय 2 साथ खत्म। क्या कोई पुस्तकालय है जो प्रतीकात्मक भेदभाव का समर्थन करता है? कोई अन्य सुझाव?

+0

अपना रोलिंग एक बुरा विचार होगा। मैंने कंप्यूटर बीजगणित में एक क्रॉस-सूचीबद्ध ग्रेड कोर्स लिया है, और चीजें भी काफी सुविधा नहीं हैं। मैट नियमों को लागू करके सरलीकृत भेदभाव किया जा सकता है और फिर विकल्प और मूल्यांकन करने की कोशिश की जा सकती है ... सी/सी ++ में करना मुश्किल है। – Calyth

+0

भी देखें http://stackoverflow.com/questions/627055/compute-a-derivative-using-discrete-methods और हो सकता है आपके सवाल का व्युत्पन्न –

उत्तर

5

संख्यात्मक भेदभाव "दाएं" (त्रुटियों को कम करने के अर्थ में) प्राप्त करना काफी मुश्किल हो सकता है। शुरू करने के लिए, आप numerical derivatives पर संख्यात्मक प्राप्तकर्ता अनुभाग पर एक नज़र डालना चाहेंगे।

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

व्यावसायिक अंत में, गणित और मेपल दोनों में सी एपीआई हैं। पुस्तकालयों का उपयोग करने के लिए आपको प्रोग्राम के एक स्थापित/लाइसेंस प्राप्त संस्करण की आवश्यकता है, लेकिन दोनों आसानी से आपके द्वारा अनुसरण किए जाने वाले प्रतीकात्मक भिन्नता के प्रकार को आसानी से कर सकते हैं।

0

यह एक तरफ है क्योंकि यह लिस्प पर लागू होता है और सी/सी ++ नहीं, लेकिन यह दूसरों को समान कार्यों की तलाश करने में मदद कर सकता है या आप स्वयं को सी/सी ++ में समान कुछ लागू करने पर कुछ विचार प्राप्त कर सकते हैं। ,

  1. व्युत्पन्न नियम 3b
  2. बीजीय नियम 4a

लिस्प में यह बहुत सीधे आगे है (और शक्तिशाली पैटर्न मिलान और बहुरूपी के साथ अन्य कार्यात्मक भाषाओं में: SICP तुतलाना के लिए इस विषय पर कुछ व्याख्यान है प्रकार)। सी में, आपको संभवतः एक ही शक्ति प्राप्त करने के लिए enums और structs का भारी उपयोग करना होगा (आवंटन/अस्वीकरण का उल्लेख नहीं करना)। एक निश्चित रूप से कोड कर सकता है जो आपको ओकंपल में एक घंटे से कम समय में चाहिए - मैंने कहा कि टाइपिंग गति सीमित कारक है। यदि आपको सी की आवश्यकता है, तो आप वास्तव में सी (और इसके विपरीत) से ओकंपल को कॉल कर सकते हैं।

+0

वास्तव में टैग करना होगा। प्रतीकात्मक गणित सी में एक दुःस्वप्न होगाबस मॉलॉक्स प्राप्त करना और सही से मुक्त होना उच्च स्तर की कार्यात्मक भाषा का उपयोग करने से अधिक समय लेगा। – Jules

+0

मैंने शुरुआत में इसके बारे में भी सोचा नहीं था (मुझे लगता है कि जीसी के साथ कार्यात्मक भाषाओं का उपयोग करने के लिए भी उपयोग किया जाता है)। लेकिन आप अतिरिक्त रूप से सही हैं। यह एक दुःस्वप्न होगा। – nlucaroni

+0

गणित का मूल सी में लिखा गया है, इसलिए, यह संभव है। – alfC

11

मैंने कई पुस्तकालयों में ऐसी पुस्तकालयों को लागू किया है, लेकिन दुर्भाग्य से सी नहीं। यदि आप केवल बहुपद (रकम, उत्पाद, चर, स्थिरांक, और शक्तियों) से निपट रहे हैं तो यह बहुत आसान है। ट्रिग फ़ंक्शन भी बहुत खराब नहीं हैं। कुछ भी जटिल और आप किसी और की लाइब्रेरी को मास्टर करने के लिए समय निकालने से बेहतर होंगे।

आप अपने खुद के रोल करने का फैसला करते हैं, मैं कुछ सुझाव है कि अपने जीवन को आसान बनाने में होगा:

  • उपयोग अपरिवर्तनीय डेटा संरचनाओं (पूरी तरह कार्यात्मक डेटा संरचनाओं) भाव का प्रतिनिधित्व करने के लिए।

  • आपके लिए स्मृति प्रबंधित करने के लिए Hans Boehm's garbage collector का उपयोग करें।

  • रैखिक योग का प्रतिनिधित्व करने के लिए, एक सीमित मानचित्र का उपयोग करें (उदा।, एक बाइनरी सर्च ट्री) प्रत्येक चर को अपने गुणांक में मैप करने के लिए।

आप अपनी सी कोड में Lua एम्बेड करने के लिए तैयार हैं और वहाँ अपने संगणना करते हैं, मैं http://www.cs.tufts.edu/~nr/drop/lua पर मेरे लुआ कोड डाल दिया है। अच्छी सुविधाओं में से एक यह है कि यह एक प्रतीकात्मक अभिव्यक्ति ले सकता है, इसे अलग कर सकता है, और परिणामों को लुआ में संकलित कर सकता है। आपको निश्चित रूप से कोई दस्तावेज नहीं मिलेगा :-(

1

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

आप रुचि के गणितीय तरीकों के लिए एक इंटरफेस को परिभाषित करते हैं (जैसे, जोड़ने/उप/mul/div/अंतर/एकीकृत), तो आप देख रहे हैं एक गोफ समग्र पैटर्न पर। टर्म और बहुपद दोनों इंटरफ़ेस को कार्यान्वित करेंगे। पॉलिनोमियल बस अपने संग्रह में प्रत्येक टर्म पर फिर से सक्रिय होगा।

1

यह निश्चित रूप से मौजूदा पैकेज का लाभ उठाना आसान होगा अपना खुद का लिखने के लिए, लेकिन यदि आप अपना खुद का लिखने के लिए दृढ़ हैं, और आप सी ++ के कुछ अंधेरे कोनों के बारे में कुछ समय बिताने के लिए तैयार हैं, तो आप Boost से अपनी लाइब्रेरी इंजीनियर करने के लिए उपयोग कर सकते हैं।

असल में, Boost.Proto, किसी मान्य सी ++ अभिव्यक्ति कन्वर्ट करने के लिए अनुमति देता है इस तरह के रूप x * x + y * y एक expression template के लिए - मूल रूप से है कि अभिव्यक्ति की पार्स पेड़ का प्रतिनिधित्व नेस्टेड struct s का उपयोग करके - और फिर उस पर किसी भी मनमाने ढंग से गणना प्रदर्शन बाद में proto::eval() पर कॉल करके पार्स पेड़। डिफ़ॉल्ट रूप से, proto::eval() का उपयोग पेड़ का मूल्यांकन करने के लिए किया जाता है जैसे कि यह सीधे चलाया गया था, हालांकि कोई कारण नहीं है कि आप प्रत्येक फ़ंक्शन या ऑपरेटर के व्यवहार को इसके बजाय प्रतीकात्मक व्युत्पन्न करने के लिए संशोधित नहीं कर पाएंगे।

हालांकि यह आपकी समस्या के अत्यंत जटिल समाधान होगा, फिर भी यह C++ टेम्पलेट मेटाप्रोग्रामिंग तकनीकों का उपयोग करके अपने स्वयं के अभिव्यक्ति टेम्पलेट्स को रोल करने का प्रयास करने से कहीं अधिक आसान होगा।

+0

बूस्ट-प्रोटो के बारे में मैंने पहले सुना है और मैं अभी भी अस्पष्ट हूं कि बूस्ट-प्रोटो में क्या मूल्य प्रदान किया जाता है। –

+0

@ उपयोगकर्ता 67826 9: 2 कारण: (1) अभिव्यक्ति। आप आसानी से एएसटी डेटा संरचनाओं को बनाने के लिए इसका उपयोग कर सकते हैं, उदा। एक अभिव्यक्ति का प्रतिनिधित्व करता है 'x * x + y * y' बस अपने कोड में उस C++ अभिव्यक्ति verbatim टाइप करके; यदि आपने एएसटी में हेरफेर करने के लिए कोड लिखा है (उदाहरण के लिए मूल्यांकन, संकलन, सुंदर मुद्रण या (गणितीय अभिव्यक्तियों के लिए) अलग-अलग/एकीकृत/विस्तार/सरलीकृत करने के लिए आप इसे लागू कर सकते हैं। ... –

+0

... (2) दक्षता। यदि आप केवल अभिव्यक्ति का मूल्यांकन करना चाहते हैं, तो सामान्य सी ++ कंप्यूटेशंस अनावश्यक रूप से कई अस्थायी रूप से बनाए और नष्ट कर देगा; आप अक्सर एएसटी का निर्माण और मूल्यांकन करके बेहतर कर सकते हैं, जो कस्टम-निर्मित कन्स्ट्रक्टर की तरह थोड़ा व्यवहार करता है जो केवल एक स्मृति आवंटन करता है (अधिक जानकारी के लिए पहला Google परिणाम देखें) –

5

आप संख्यात्मक भेदभाव कर रहे हैं ("f (x)पर एक्स = x0 के व्युत्पन्न का मूल्यांकन") और आप जानते हैं कि आप पहले से समीकरण (यानी, उपयोगकर्ता इनपुट नहीं) कर रहे हैं, तो मैं FADBAD++ की सिफारिश करता हूं। यह Automatic differentiation का उपयोग कर संख्यात्मक डेरिवेटिव को हल करने के लिए एक सी ++ टेम्पलेट लाइब्रेरी है। यह बहुत तेज़ और सटीक है।

+0

इस लाइब्रेरी का सुझाव देने के लिए धन्यवाद। मैंने दो बार जांच की है और ओपी के लिए उत्तर पोस्ट किया है। यह बहुत अच्छी लाइब्रेरी प्रतीत होता है। धन्यवाद। – CroCo

0

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

  • मूल्य
  • व्युत्पन्न मान बनाम स्वतंत्र चरों

की एक सरणी तो आप जोड़ और घटाव के लिए ऑपरेटरों और इतने पर और पाप की तरह काम करता है लिखना हैं की जरूरत है() जो इस ऑपरेशन के लिए बुनियादी और जाने-माने नियमों को लागू करता है।

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

छोटा कर दिया टेलर श्रृंखला - वहाँ दो पुस्तकालयों इस लिए उपलब्ध हैं:

http://code.google.com/p/libtaylor/

http://www.foelsche.com/ctaylor

4

आप दो आसान तरीके

  1. में अपने संख्यात्मक भेदभाव की सटीकता में सुधार कर सकते हैं

    एक छोटे डेल्टा का प्रयोग करें। ऐसा लगता है कि आपने लगभग 1e-2 का मान उपयोग किया है। 1e-8 के साथ शुरू करें, और परीक्षण करें यदि कोई छोटा दर्द होता है या मदद करता है। जाहिर है आप मशीन परिशुद्धता के बहुत करीब नहीं जा सकते - लगभग 1e-16 डबल के लिए।

  2. उपयोग केंद्रीय बजाय आगे (या पीछे की ओर) मतभेद मतभेद। अर्थात df_dx =(f(x+delta) - f(x-delta))/(2.0*delta) कारणों उच्च काट-छांट मामले को रद्द करने के साथ क्या करना के लिए, केंद्रीय मतभेद अनुमान में त्रुटि आदेश delta^2 बजाय आगे मतभेद की डेल्टा के है। देखें http://en.wikipedia.org/wiki/Finite_difference

0

थेनो पर एक नज़र डालें, यह प्रतीकात्मक भेदभाव (तंत्रिका जाल के संदर्भ में) का समर्थन करता है। परियोजना ओपन सोर्स है हालांकि आपको यह देखने में सक्षम होना चाहिए कि वे इसे कैसे करते हैं।

6 साल के बाद इस को लाने के लिए
0

क्षमा करें। हालांकि, मैं अपनी परियोजना में ऐसी लाइब्रेरी की तलाश में था और मैंने देखा है @ एडीफाई FADBAD++ सुझाता है। मैंने प्रलेखन पढ़ा है और आपके प्रश्न पर वापस आ गया है। मुझे लगता है कि मेरा जवाब फायदेमंद होगा, इसलिए, निम्नलिखित कोड आपके मामले के लिए है।

#include <iostream> 
#include "fadiff.h" 

using namespace fadbad; 

F<double> func(const F<double>& x, const F<double>& y) 
{ 
    return x*x + y*y; 
} 

int main() 
{ 
    F<double> x,y,f;  // Declare variables x,y,f 
    x=1;     // Initialize variable x 
    x.diff(0,2);   // Differentiate with respect to x (index 0 of 2) 
    y=1;     // Initialize variable y 
    y.diff(1,2);   // Differentiate with respect to y (index 1 of 2) 
    f=func(x,y);   // Evaluate function and derivatives 

    double fval=f.x(); // Value of function 
    double dfdx=f.d(0); // Value of df/dx (index 0 of 2) 
    double dfdy=f.d(1); // Value of df/dy (index 1 of 2) 

    std::cout << " f(x,y) = " << fval << std::endl; 
    std::cout << "df/dx(x,y) = " << dfdx << std::endl; 
    std::cout << "df/dy(x,y) = " << dfdy << std::endl; 

    return 0; 
} 

उत्पादन

f(x,y) = 2 
df/dx(x,y) = 2 
df/dy(x,y) = 2 

एक और उदाहरण है, मान लें कि हम sin() के पहले व्युत्पन्न में रुचि रखते हैं करते हैं। विश्लेषणात्मक रूप से, यह cos है। यह बहुत अच्छा है क्योंकि हमें किसी दिए गए फ़ंक्शन के वास्तविक व्युत्पन्न और वास्तविक संख्या की गणना करने के लिए इसके संख्यात्मक समकक्ष की तुलना करने की आवश्यकता है। https://github.com/MartinKosicky/auto_diff/blob/master/sample/main.cpp

उपयोग किया जाता है काफी सरल है, यह भी मैट्रिक्स का समर्थन करता है:

#include <iostream> 
#include "fadiff.h" 

using namespace fadbad; 

F<double> func(const F<double>& x) 
{ 
    return sin(x); 
} 



int main() 
{ 
    F<double> f,x; 
    double dfdx; 
    x = 0.0; 
    x.diff(0,1); 
    f = func(x); 
    dfdx=f.d(0); 


    for (int i(0); i < 8; ++i){ 
     std::cout << "  x: " << x.val()  << "\n" 
        << " f(x): " << f.x()   << "\n" 
        << " fadDfdx: " << dfdx   << "\n" 
        << "trueDfdx: " << cos(x.val()) << std::endl; 
     std::cout << "==========================" << std::endl; 

     x += 0.1; 
     f = func(x); 
     dfdx=f.d(0); 
    } 


    return 0; 
} 

परिणाम

 x: 0 
    f(x): 0 
fadDfdx: 1 
trueDfdx: 1 
========================== 
     x: 0.1 
    f(x): 0.0998334 
fadDfdx: 0.995004 
trueDfdx: 0.995004 
========================== 
     x: 0.2 
    f(x): 0.198669 
fadDfdx: 0.980067 
trueDfdx: 0.980067 
========================== 
     x: 0.3 
    f(x): 0.29552 
fadDfdx: 0.955336 
trueDfdx: 0.955336 
========================== 
     x: 0.4 
    f(x): 0.389418 
fadDfdx: 0.921061 
trueDfdx: 0.921061 
========================== 
     x: 0.5 
    f(x): 0.479426 
fadDfdx: 0.877583 
trueDfdx: 0.877583 
========================== 
     x: 0.6 
    f(x): 0.564642 
fadDfdx: 0.825336 
trueDfdx: 0.825336 
========================== 
     x: 0.7 
    f(x): 0.644218 
fadDfdx: 0.764842 
trueDfdx: 0.764842 
========================== 
1

मैं सी ++ में इस तरह के एक पुस्तकालय बनाया है, आप नमूना यहाँ देख सकते हैं है। मैंने इसे आवर्ती तंत्रिका नेटवर्क बनाने के लिए उपयोग किया ... मुझे GPU मैट्रिक्स गुणा जोड़ने की आवश्यकता होगी हालांकि

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