2011-02-07 38 views
3

我認爲這個答案有點複雜,因爲它涉及幾件事情。使用Rcpp的R上的檸檬圖庫

我想用R(尤其是圖形(網絡))進行高性能計算。作爲R包igraph是非常好的。但是R很慢,所以我想用C++編寫昂貴的例程(可能用C語言)。我看了一下C庫,發現它有點混亂。我也看看Boost Graph Library,我讀到它很難學。所以我最終找到了Lemon Graph Library。它使用C++,看起來非常好用。

所以我按照官方頁面的建議安裝了檸檬圖庫。然後使用Rcpp內聯包我管理自己從R運行Lemon Graph C++代碼。Here我詳細寫了我所做的。在myexample_inline.R文件

inc <- ' 
      #include <lemon/list_graph.h> 
      using namespace lemon ; 
      ' 


    src <- ' 
      int xx = Rcpp::as<int>(x); 

      int res = xx + 1; 

      ListDigraph g; 

      ListDigraph::Node u = g.addNode(); 
      ListDigraph::Node v = g.addNode(); 
      ListDigraph::Arc a = g.addArc(u, v); 

      int i = countNodes(g); 
      int j = countArcs(g); 

      Rprintf("num nodes is %d , and num edges is %d \\n",i,j); 

      return Rcpp::wrap(res); 
      ' 

     fun <- cxxfunction(signature(x="numeric"), body=src,include=inc, plugin="Rcpp") 

,然後運行A R控制檯,並寫上::但基本上我把這個

> library("inline") 
> library("Rcpp") 
> source("myexample_inline.R") 
> fun(1) 
num nodes is 2 , and num edges is 1 
[1] 2 

所以它的工作原理!但是現在我有以下問題。如果我創建一個C++函數(比如double func1(g)),例如計算一些檸檬圖對象的屬性。我如何從內聯代碼調用該函數?我必須將func1()作爲模板函數,並將其放入cxxfunction()的include字段中?

基本上我不知道如何調用另一個C語言函數內嵌在R中的C++函數。有沒有使用內聯代碼的另一種方法?

也許我可以做到這一點使用Rcpp模塊但我不能(仍然)弄清楚如何做到這一點。 我在製作模塊時遇到問題。我會繼續嘗試,但也許我可以從這裏得到一些提示。

我也想過開發(我的第一個)包的可能性。但是我有檸檬圖C++代碼調用這樣的標題(例如)問題:

#include <iostream> 
#include <lemon/list_graph.h> 

因此,這意味着(至少我相信這一點),我不能避免檸檬圖的安裝圖書館。如果我想製作一個檸檬圖庫的R包,我必須「重寫」所有的代碼!!!所以這不是我的主要選擇。

問候

+0

將一些預包裝就像http://pinard.progiciels-bpi.ca/libR/library/graph/doc/index.html爲你工作? – 2011-02-07 01:19:49

+0

您可能需要將五個標籤中的一個換成`r`。 – 2011-02-07 01:40:22

回答

1

你好,感謝在Rcpp的興趣。

要綁定不同庫函數之間的調用,您可能需要考慮構建一個包。現在有20個軟件包使用Rcpp列出on the Rcpp page on CRAN,因此您可以從中複製示例。在第一次應用時,這是寫一個正常的程序沒有不同,只是RCPP幫助你得到它的R.

如果您有更多疑問,請隨時把他們帶到rcpp-devel列表。

+0

@Jeremiah Willcock:我必須更仔細地看待你的答案。但在第一種觀點中,這不是我所需要的,因爲它是R代碼。我使用計算成本很高的模型(我是一名物理學家)。換句話說,我需要在C++中實現一些功能(也許是C)。 R對其他所有內容都很好,所以我非常喜歡將C++代碼集成到R. 感謝您的迴應。 @Dirk Eddelbuettel: 我會看看如何在R中構建一個包。但是如果我構建一個包,它將依賴於Lemon Graph Library,如果有人想使用`> install.package()來安裝它,它將無法工作。我是對的? – 2011-02-07 02:04:23

2

我已經成功解決了這個問題。Here你可以找到我所做過的詳細解釋。也許,這對大多數人來說是微不足道的,但對於與我處於同一位置的人來說,這可能是一個很好的起點。我會在這裏發佈我的簡歷。

首先我安裝了檸檬圖(C++)庫(LGL)。我剛從主頁下載LGL(from here)。然後我繼續:

$ tar xvzf lemon-1.2.tar.gz 
$ cd lemon-1.2 
$ ./configure 
$ make 
$ make check # This is optional, but recommended. It runs a bunch of tests. 
$ sudo make install 

然後檢查它是否有效。因此,在一個文件名爲mycode.cc我把:

#include <iostream> 
#include <lemon/list_graph.h> 

using namespace lemon; 
using namespace std; 

int main() 
{ 
    ListDigraph g; 

    ListDigraph::Node u = g.addNode(); 
    ListDigraph::Node v = g.addNode(); 
    ListDigraph::Arc a = g.addArc(u, v); 

    cout << "Hello World! This is LEMON library here." << endl; 
    cout << "We have a directed graph with " << countNodes(g) << " nodes " 
     << "and " << countArcs(g) << " arc." << endl; 

    return 0; 
} 

然後我編譯並運行它:

$ g++ -O2 mycode.cc -lemon 
... BLA BLA BLA ... 
$./a.out 
Hello World! This is LEMON library here. 
We have a directed graph with 2 nodes and 1 arc. 

所以它的工作原理。現在,想法是通過Rcpp將該代碼集成到R中。因此,在某些目錄中我打開A R控制檯,我做的:

> require("Rcpp") 
Loading required package: Rcpp 
> Rcpp.package.skeleton("pkgwithlgl") 
Creating directories ... 
Creating DESCRIPTION ... 
Creating NAMESPACE ... 
Creating Read-and-delete-me ... 
Saving functions and data ... 
Making help files ... 
Done. 
Further steps are described in './pkgwithlgl/Read-and-delete-me'. 

Adding Rcpp settings 
>> added Depends: Rcpp 
>> added LinkingTo: Rcpp 
>> added useDynLib directive to NAMESPACE 
>> added Makevars file with Rcpp settings 
>> added Makevars.win file with Rcpp settings 
>> added example header file using Rcpp classes 
>> added example src file using Rcpp classes 
>> added example R file calling the C++ example 
>> added Rd file for rcpp_hello_world 

所以,在這樣我就創建了一個名爲pkgwithlgl一個新的基於RCPP源碼包。現在在pkgwithlgl目錄(它是我想要修改和安裝的軟件包的源代碼)內有一個名爲src的目錄。裏面有包含C++代碼的文件。尤其是,存在一個名爲* rcpp_hello_world.cpp *包含:

#include "rcpp_hello_world.h" 

SEXP rcpp_hello_world(){ 
    using namespace Rcpp ; 

    CharacterVector x = CharacterVector::create("foo", "bar") ; 
    NumericVector y = NumericVector::create(0.0, 1.0) ; 
    List z   = List::create(x, y) ; 

    return z ; 
} 

現在,我修改它,所以它變成了:

#include "rcpp_hello_world.h" 
#include <lemon/list_graph.h> 
using namespace lemon ; 

SEXP rcpp_hello_world(){ 
    using namespace Rcpp ; 

    int res = 1; 

    ListDigraph g; 

    ListDigraph::Node u = g.addNode(); 
    ListDigraph::Node v = g.addNode(); 
    ListDigraph::Arc a = g.addArc(u, v); 

    int i = countNodes(g); 
    int j = countArcs(g); 

    Rprintf("num nodes is %d , and num edges is %d \n",i,j); 

    return wrap(res) ; 
} 

然後,從Linux控制檯源的容器目錄包我寫:

$ R CMD INSTALL pkgwithlgl 

返回:

* installing to library ‘/home/juan/R/x86_64-pc-linux-gnu-library/2.12’ 
* installing *source* package ‘pkgwithlgl’ ... 
** libs 
g++ -I/usr/share/R/include -I"/usr/local/lib/R/site-library/Rcpp/include" -fpic -O3  -pipe -g -c rcpp_hello_world.cpp -o rcpp_hello_world.o 
g++ -shared -o pkgwithlgl.so rcpp_hello_world.o -L/usr/local/lib/R/site-library/Rcpp/lib  -lRcpp -Wl,-rpath,/usr/local/lib/R/site-library/Rcpp/lib -L/usr/lib64/R/lib -lR 
installing to /home/juan/R/x86_64-pc-linux-gnu-library/2.12/pkgwithlgl/libs 
** R 
** preparing package for lazy loading 
** help 
Warning:  /home/juan/Desktop/facu/investigacion_ensayos/Cosas_crudas/programming_coding/R-work- space/integrating_R_with_cpp_via_Rcpp/using_packages/pkgwithlgl/man/pkgwithlgl- package.Rd:32: All text must be in a section 
Warning:  /home/juan/Desktop/facu/investigacion_ensayos/Cosas_crudas/programming_coding/R-work- space/integrating_R_with_cpp_via_Rcpp/using_packages/pkgwithlgl/man/pkgwithlgl- package.Rd:33: All text must be in a section 
*** installing help indices 
    converting help for package ‘pkgwithlgl’ 
    finding HTML links ... done 
    pkgwithlgl-package      html 
    rcpp_hello_world      html 
** building package indices ... 
** testing if installed package can be loaded 

* DONE (pkgwithlgl)  

因此,軟件包已安裝(警告與我沒有以正確的方式填充.Rd文件,即包含有關軟件包的幫助文件的事實有關)。我打開一個R控制檯,並寫道:

> require("pkgwithlgl") 
Loading required package: pkgwithlgl 
Loading required package: Rcpp 
> rcpp_hello_world() 
num nodes is 2 , and num edges is 1 
[1] 1 

所以它的工作!就這些。

但是嘿!如果我構建這個包並將其上傳到(例如)CRAN(我不會這麼做)會發生什麼。如果有人從CRAN安裝這個軟件包,它會爲他工作嗎?即使它不安裝LGL包?

問候