C ++ में LAPACK का उपयोग कैसे शुरू करें?


10

मैं कम्प्यूटेशनल विज्ञान के लिए नया हूं और मैंने पहले से ही एकीकरण के लिए बुनियादी तरीकों, प्रक्षेप, RK4, न्यूमेरोव आदि जैसे तरीकों को c ++ पर सीखा है, लेकिन हाल ही में मेरे प्रोफेसर ने मुझसे पूछा कि मैट्रिस से संबंधित समस्याओं को हल करने के लिए LAPACK का उपयोग कैसे करें। उदाहरण के लिए एक जटिल मैट्रिक्स के eigenvalues ​​खोजने के लिए। मैंने कभी भी तीसरे पक्ष के पुस्तकालयों का उपयोग नहीं किया है और मैं लगभग हमेशा अपने स्वयं के कार्यों को लिखता हूं। मैं कई दिनों से आस-पास खोज रहा हूं लेकिन लैपैक के लिए कोई भी शौकिया-अनुकूल मार्गदर्शक नहीं मिल रहा है। उन सभी को उन शब्दों में लिखा गया है जो मुझे समझ में नहीं आते हैं और मुझे नहीं पता कि पहले से ही लिखित कार्यों का उपयोग करना इस जटिल क्यों होना चाहिए। वे ज़गेव, डीटीएसआरवी, इत्यादि शब्दों से भरे हुए हैं और मैं निराश हूं। मैं इस छद्म कोड की तरह कुछ कोड करना चाहता हूं:

#include <lapack:matrix>
int main(){
  LapackComplexMatrix A(n,n);
  for...
   for...
    cin>>A(i,j);
  cout<<LapackEigenValues(A);
  return 0;
}

मुझे नहीं पता कि मैं मूर्ख या शौकिया हूं। लेकिन फिर, यह है कि यह मुश्किल नहीं होना चाहिए? मुझे यह भी नहीं पता कि मुझे LAPACK या LAPACK ++ का उपयोग करना चाहिए। (मैं सी ++ में कोड लिखता हूं और पाइथन या फोरट्रान का कोई ज्ञान नहीं है) और उन्हें कैसे स्थापित किया जाए।


शायद यह उदाहरण उपयोगी होगा: Chromprogramming.com/files/code/LAPACK
nukeguy

यदि आप अभी शुरू कर रहे हैं, तो शायद एक पुस्तकालय का उपयोग करना आसान होगा जो कि ArrayFire github.com/arrayfire/arrayfire की तरह सरल है । आप इसे C ++ से सीधे कॉल कर सकते हैं और एपीआई सरल हैं और मुझे लगता है कि यह उन सभी कार्यों को कर सकता है जो LAPACK करता है।
विक्रम

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

LAPACK फ़ंक्शन को सीधे कॉल करना बहुत थकाऊ और त्रुटि प्रवण है। LAPACK के लिए कई उपयोगकर्ता के अनुकूल C ++ रैपर हैं जो बहुत आसान उपयोग प्रदान करते हैं, जैसे कि आर्मैडिलो । जटिल ईजन अपघटन के विशिष्ट उपयोग के मामले के लिए, उपयोगकर्ता के अनुकूल eig_gen () फ़ंक्शन को देखें, जो इस LAPACK राक्षसीता, झेव (JOBZ, UPLO, N, A, LDA, W, WORK, LWORK, RWORK, INFO) को लपेटता है। और प्राप्त किए गए eigenvalues ​​और eigenvectors को मानक अभ्यावेदन में सुधार करता है।
hbrerkere

जवाबों:


18

मैं कुछ अन्य उत्तरों से असहमत होने जा रहा हूं और कहता हूं कि मेरा मानना ​​है कि वैज्ञानिक कंप्यूटिंग के क्षेत्र में LAPACK का उपयोग कैसे किया जाए यह महत्वपूर्ण है।

हालांकि, लैपैक का उपयोग करने के लिए एक बड़ा सीखने की अवस्था है। ऐसा इसलिए है क्योंकि यह बहुत निचले स्तर पर लिखा गया है। इसका नुकसान यह है कि यह बहुत ही गूढ़ लगता है, और इंद्रियों के लिए सुखद नहीं है। इसका लाभ यह है कि इंटरफ़ेस अस्पष्ट है और मूल रूप से कभी नहीं बदलता है। इसके अतिरिक्त, LAPACK के कार्यान्वयन, जैसे कि इंटेल मठ कर्नेल लाइब्रेरी वास्तव में तेज़ हैं।

अपने स्वयं के प्रयोजनों के लिए, मेरे पास अपने उच्च स्तर के C ++ वर्ग हैं जो LAPACK सबरूटीन के चारों ओर लपेटते हैं। कई वैज्ञानिक पुस्तकालय भी नीचे की ओर LAPACK का उपयोग करते हैं। कभी-कभी उनका उपयोग करना आसान होता है, लेकिन मेरे विचार में उपकरण को समझने में बहुत अधिक मूल्य है। उस अंत तक, मैंने आपको शुरू करने के लिए LAPACK का उपयोग करते हुए C ++ में लिखा एक छोटा सा कार्य उदाहरण प्रदान किया है। यह उबंटू में liblapack3स्थापित पैकेज के साथ काम करता है , और भवन के लिए अन्य आवश्यक पैकेज। इसका उपयोग संभवतः अधिकांश लिनक्स वितरण में किया जा सकता है, लेकिन लैपैक की स्थापना और इसके खिलाफ लिंक करना अलग-अलग हो सकता है।

यहाँ फ़ाइल है test_lapack.cpp

#include <iostream>
#include <fstream>


using namespace std;

// dgeev_ is a symbol in the LAPACK library files
extern "C" {
extern int dgeev_(char*,char*,int*,double*,int*,double*, double*, double*, int*, double*, int*, double*, int*, int*);
}

int main(int argc, char** argv){

  // check for an argument
  if (argc<2){
    cout << "Usage: " << argv[0] << " " << " filename" << endl;
    return -1;
  }

  int n,m;
  double *data;

  // read in a text file that contains a real matrix stored in column major format
  // but read it into row major format
  ifstream fin(argv[1]);
  if (!fin.is_open()){
    cout << "Failed to open " << argv[1] << endl;
    return -1;
  }
  fin >> n >> m;  // n is the number of rows, m the number of columns
  data = new double[n*m];
  for (int i=0;i<n;i++){
    for (int j=0;j<m;j++){
      fin >> data[j*n+i];
    }
  }
  if (fin.fail() || fin.eof()){
    cout << "Error while reading " << argv[1] << endl;
    return -1;
  }
  fin.close();

  // check that matrix is square
  if (n != m){
    cout << "Matrix is not square" <<endl;
    return -1;
  }

  // allocate data
  char Nchar='N';
  double *eigReal=new double[n];
  double *eigImag=new double[n];
  double *vl,*vr;
  int one=1;
  int lwork=6*n;
  double *work=new double[lwork];
  int info;

  // calculate eigenvalues using the DGEEV subroutine
  dgeev_(&Nchar,&Nchar,&n,data,&n,eigReal,eigImag,
        vl,&one,vr,&one,
        work,&lwork,&info);


  // check for errors
  if (info!=0){
    cout << "Error: dgeev returned error code " << info << endl;
    return -1;
  }

  // output eigenvalues to stdout
  cout << "--- Eigenvalues ---" << endl;
  for (int i=0;i<n;i++){
    cout << "( " << eigReal[i] << " , " << eigImag[i] << " )\n";
  }
  cout << endl;

  // deallocate
  delete [] data;
  delete [] eigReal;
  delete [] eigImag;
  delete [] work;


  return 0;
}

यह कमांड लाइन का उपयोग करके बनाया जा सकता है

g++ -o test_lapack test_lapack.cpp -llapack

यह एक निष्पादन योग्य नाम का उत्पादन करेगा test_lapack। मैंने इसे एक टेक्स्ट इनपुट फ़ाइल में पढ़ने के लिए सेट किया है। यहाँ एक फाइल है जिसका नाम matrix.txt3x3 मैट्रिक्स है।

3 3
-1.0 -8.0  0.0
-1.0  1.0 -5.0
 3.0  0.0  2.0

प्रोग्राम को चलाने के लिए बस टाइप करें

./test_lapack matrix.txt

कमांड लाइन पर, और आउटपुट होना चाहिए

--- Eigenvalues ---
( 6.15484 , 0 )
( -2.07742 , 3.50095 )
( -2.07742 , -3.50095 )

टिप्पणियाँ:

  • आप LAPACK के लिए नामकरण योजना द्वारा फेंक दिए गए लगते हैं। एक संक्षिप्त विवरण यहाँ है
  • DGEEV सबरूटीन के लिए इंटरफ़ेस यहाँ है । आपको वहाँ के तर्कों के विवरण की तुलना करने में सक्षम होना चाहिए जो मैंने यहाँ किया है।
  • extern "C"शीर्ष पर अनुभाग पर ध्यान दें , और मैंने अंडरस्कोर जोड़ा है dgeev_। ऐसा इसलिए है क्योंकि पुस्तकालय फोरट्रान में लिखा और बनाया गया था, इसलिए लिंक करते समय प्रतीकों से मेल खाना आवश्यक है। यह कंपाइलर और सिस्टम पर निर्भर है, इसलिए यदि आप विंडोज पर इसका उपयोग करते हैं, तो इसे सभी को बदलना होगा।
  • कुछ लोग L इंटरफ़ेस पर C इंटरफ़ेस का उपयोग करने का सुझाव दे सकते हैं । वे सही हो सकते हैं, लेकिन मैंने हमेशा इसे इस तरह से किया है।

3
आप जिस चीज़ की तलाश कर रहे हैं, उसमें से कुछ त्वरित Googlage के साथ मिल सकते हैं। शायद आप अभी निश्चित नहीं हैं कि क्या खोजा जाए। Netlib LAPACK का रक्षक है। प्रलेखन यहाँ पाया जा सकता हैइस पृष्ठ में LAPACK की मुख्य कार्यक्षमता की एक आसान तालिका है। कुछ महत्वपूर्ण हैं (1) समीकरणों के हल करने की प्रणाली, (2) eigenvalue समस्याएं, (3) एकवचन मान विघटन, और (4) क्यूआर कारक। क्या आपने DGEEV के लिए मैनुअल को समझा?
लेडहेड

1
वे सभी एक ही चीज़ के लिए अलग-अलग इंटरफेस हैं। LAPACK मूल है। यह फोरट्रान में लिखा गया है, इसलिए इसका उपयोग करने के लिए आपको सी / सी ++ काम से क्रॉस-संकलन करने के लिए कुछ गेम खेलना होगा, जैसे मैंने दिखाया। मैंने कभी भी LAPACKE का उपयोग नहीं किया है, लेकिन ऐसा लगता है कि यह LAPACK के ऊपर एक बहुत पतली सी आवरण है जो इस क्रॉस संकलन व्यवसाय से बचता है, लेकिन यह अभी भी बहुत कम है। LAPACK ++ प्रतीत होता है कि यह उच्च स्तर का C ++ आवरण है, लेकिन मुझे नहीं लगता कि यह अब भी समर्थित है (कोई मुझे गलत कहे तो सही)।
लेडहेड

1
मुझे किसी विशिष्ट कोड संग्रह का पता नहीं है। लेकिन यदि आप किसी भी LAPACK सबरूटिन नाम के Google को देखते हैं, तो आप StackExchange साइटों में से किसी एक पर एक पुराना प्रश्न जान सकते हैं।
लेडहेड

1
@AlirezaHashemi वैसे, आपको वर्क सरणी प्रदान करने का कारण यह है क्योंकि एक नियम के रूप में लैपैक अपने सबरूटीन्स के अंदर कोई मेमोरी आवंटित नहीं करता है। यदि हम LAPACK का उपयोग कर रहे हैं, तो हम संभवत: मेमोरी के gobs का उपयोग कर रहे हैं, और मेमोरी को आवंटित करना महंगा है, इसलिए यह कॉलिंग रूटीन को मेमोरी आवंटन के प्रभारी बनाने के लिए समझ में आता है। चूंकि DGEEV को मध्यवर्ती मात्रा को स्टोर करने के लिए मेमोरी की आवश्यकता होती है, इसलिए हमें उस कार्य स्थान को प्रदान करना होगा।
लेडहेड

1
समझ गया। और मैंने सफलतापूर्वक zgeev का उपयोग करके एक जटिल मैट्रिक्स के eigenvalues ​​की गणना करने के लिए अपना पहला कोड लिखा था। और पहले से ही अधिक कर रहा है! धन्यवाद!
एलिरज़ा

7

मैं आमतौर पर लोगों को यह बताने का विरोध करता हूं कि मुझे क्या लगता है कि उन्हें अपने सवाल का जवाब देने के बजाय क्या करना चाहिए लेकिन इस मामले में मैं एक अपवाद बनाने जा रहा हूं।

लापैक फोरट्रान में लिखा है और एपीआई बहुत फोरट्रान की तरह है। लैपैक के लिए एक सी एपीआई है जो इंटरफ़ेस को थोड़ा कम दर्दनाक बनाता है लेकिन सी ++ से लैपैक का उपयोग करना कभी भी सुखद अनुभव नहीं होगा।

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

#include <iostream>
using std::cout;
using std::endl;

#include <Eigen/Eigenvalues>

int main()
{
  const int n = 4;
  Eigen::MatrixXd a(n, n);
  a <<
    0.35, 0.45, -0.14, -0.17,
    0.09, 0.07, -0.54, 0.35,
    -0.44, -0.33, -0.03, 0.17,
    0.25, -0.32, -0.13, 0.11;
  Eigen::EigenSolver<Eigen::MatrixXd> es;
  es.compute(a);
  Eigen::VectorXcd ev = es.eigenvalues();
  cout << ev << endl;
}

यह उदाहरण eigenvalue समस्या लापैक फ़ंक्शन के लिए एक परीक्षण मामला है dgeev। आप इस समस्या dgeev उदाहरण के लिए FORTRAN कोड और परिणाम देख सकते हैं और अपनी तुलना कर सकते हैं।


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

ओह, वे अधिभार operator,! ऐसा कभी नहीं देखा गया कि वास्तविक अभ्यास :-)
वोल्फगैंग बैंगर्थ

1
वास्तव में, यह operator,अधिभार पहले की तुलना में अधिक दिलचस्प / बेहतर है। इसका उपयोग मैट्रिसेस को इनिशियलाइज़ करने के लिए किया जाता है। मैट्रिक्स को शुरू करने वाली प्रविष्टियाँ स्केलर स्थिरांक हो सकती हैं, लेकिन पहले से परिभाषित मेट्रिसेस या सब-मैट्रिसेस भी हो सकती हैं। बहुत MATLAB की तरह। काश मेरी C ++ प्रोग्रामिंग की क्षमता इतनी अच्छी होती कि वह अपने आप को परिष्कृत करने वाली चीज़ को लागू कर सकती थी ;-)
बिल ग्रीन

7

यहाँ ऊपर के रूप में एक ही नस में एक और जवाब है।

आपको आर्मडिलो सी ++ लीनियर बीजगणित पुस्तकालय में देखना चाहिए ।

पेशेवरों:

  1. फ़ंक्शन सिंटैक्स उच्च-स्तरीय (MATLAB के समान) है। तो कोई DGESVमंबो-जंबो, बस X = solve( A, B )(हालांकि उन अजीब-से दिखने वाले LAPACK फ़ंक्शन नामों के पीछे एक कारण है ...)।
  2. विभिन्न मैट्रिक्स डिकम्पोज़िशन (LU, QR, eigenvalues, SVD, Cholesky, आदि)
  3. सही तरीके से इस्तेमाल करने पर यह तेज होता है।
  4. यह अच्छी तरह से प्रलेखित है
  5. विरल मैट्रिस के लिए समर्थन है (आप बाद में इन पर गौर करना चाहेंगे)।
  6. आप इसे इष्टतम प्रदर्शन के लिए अपने सुपर-अनुकूलित BLAS / LAPACK पुस्तकालयों से जोड़ सकते हैं।

यहां देखें कि कैसे @ बिलग्रेन का कोड आर्मडिलो के साथ दिखेगा:

#include <iostream>
#include <armadillo>

using namespace std;
using namespace arma;

int main()
{
   const int k = 4;
   mat A = zeros<mat>(k,k) // mat == Mat<double>

   // with the << operator...
   A <<
    0.35 << 0.45 << -0.14 << -0.17 << endr
    0.09 << 0.07 << -0.54 << 0.35  << endr
    -0.44 << -0.33 << -0.03 << 0.17 << endr
    0.25 << -0.32 << -0.13 << 0.11 << endr;

   // but using an initializer list is faster
   A = { {0.35, 0.45, -0.14, -0.17}, 
         {0.09, 0.07, -0.54, 0.35}, 
         {-0.44, -0.33, -0.03, 0.17}, 
         {0.25, -0.32, -0.13, 0.11} };

   cx_vec eigval; // eigenvalues may well be complex
   cx_mat eigvec;

   // eigenvalue decomposition for general dense matrices
   eig_gen(eigval, eigvec, A);

   std::cout << eigval << std::endl;

   return 0;
}

आपके उत्तर और स्पष्टीकरण के लिए धन्यवाद! मैं इस लाइब्रेरी को आज़माऊंगा और अपनी ज़रूरत के हिसाब से एक सूट चुनूंगा।
एलिरेज़ा
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.