3

この答えは、いくつかのことが関係しているため、少し複雑だと思います。

特にグラフ(ネットワーク)を使用して、Rで高性能な計算を行いたいです。Rパッケージとしてigraphはとてもいいです。しかし、R は遅いので、計算コストの高いルーチンを C++ (おそらく C) でコーディングしたいと考えています。igraph C ライブラリを調べてみたところ、扱いが少し面倒であることがわかりました。また、 Boost Graph Libraryを調べて、習得が難しいという記事を読みました。それで、最終的にレモングラフライブラリを見つけました。これは C++ で書かれており、とても使いやすそうです。

そこで、公式ページで推奨されているように、Lemon Graph Library をインストールしました。次に、Rcppinlineパッケージを使用して、R から Lemon Graph C++ コードを実行するように管理します。しかし、基本的に私はこれを置く:

   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")

myexample_inline.R ファイルで、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() のインクルード フィールドに配置する必要がありますか?

基本的に: R にインライン化された別の C++ 関数から、R にインライン化された C++ 関数を呼び出す方法がわかりません。それは可能ですか? インライン コードを使用しない別の方法はありますか?

Rcppモジュールを使用してそれを行うことができるかもしれませんが、これを行う方法を(まだ)理解できませんでした。モジュールの動作に問題があります。引き続き挑戦していきますが、ここから何かヒントが得られるかもしれません。

また、(私の最初の) パッケージを開発する可能性についても考えました。しかし、Lemon Graph C++ コードがこの方法でヘッダーを呼び出すという問題がありました (たとえば)。

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

つまり、Lemon Graph Library のインストールは避けられないということです (少なくとも私はそう信じています)。Lemon Graph Library の R パッケージを作成したい場合は、すべてのコードをもう一度「書き直す」必要があります!!! したがって、これは私の主なオプションではありません。

よろしくお願いします

4

2 に答える 2

2

私はこの問題に成功しました。ここでは、私が行ったことについての詳細な説明を見つけることができます。ここにいるほとんどの人にとっては些細なことかもしれませんが、私と同じ立場にある人にとっては良い出発点になるかもしれません. 私が行ったことの履歴書をここに投稿します。

最初に、Lemon Graph (C++) Library (LGL) をインストールしました。ホームページから LGL をダウンロードしました (ここから)。それから私は進みます:

$ 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 に統合することです。したがって、あるディレクトリで 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パッケージをインストールしなくても?

よろしくお願いします

于 2011-02-11T18:34:01.783 に答える
1

Rcppに関心をお寄せいただきありがとうございます。

異なるライブラリ関数間の呼び出しをバインドするには、パッケージの構築を検討する必要があります。CRAN の Rcpp ページにリストされているように、Rcpp を使用する 20 個のパッケージがあるので、コピーする例があります。最初のアプローチでは、. これは通常のプログラムを作成することと何ら変わりはなく、Rcpp は単純にプログラムを R に移行するのに役立ちます。

さらに質問がある場合は、お気軽にrcpp-develリストに追加してください。

于 2011-02-07T01:38:41.910 に答える