【问题标题】:Lemon Graph Library on R using Rcpp使用 Rcpp 在 R 上的柠檬图库
【发布时间】:2011-02-07 01:11:05
【问题描述】:

我认为这个答案有点复杂,因为它涉及到几件事。

我想用 R 进行高性能计算,尤其是图形(网络)。作为一个 R 包 igraph 非常好。但是 R 很慢,所以我想用 C++(可能是 C)编写计算量大的例程。我查看了 igraph C 库,发现使用起来有点混乱。我还查看了 Boost Graph Library,并了解到它很难学习。所以我最终找到了Lemon Graph Library。它是用 C++ 编写的,看起来非常好用。

所以我按照官方页面的建议安装了 Lemon Graph Library。然后使用 Rcppinline 包,我管理自己从 R 运行 Lemon Graph C++ 代码。Here 我详细写了我所做的。但基本上我是这样说的:

   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)),例如计算某个 Lemon 图形对象的某些属性。我如何从内联代码中调用该函数?我必须将 func1() 作为模板函数并将其放在 cxxfunction() 的包含字段中吗?

基本上:我不知道如何从另一个也内联在 R 中的 C++ 函数调用内联在 R 中的 C++ 函数。这可能吗?还有其他不使用内联代码的方式吗?

也许我可以使用 Rcpp 模块 做到这一点,但我无法(仍然)弄清楚如何做到这一点。 我在使模块工作时遇到问题。我会继续尝试,但也许我可以从这里得到一些提示。

我还考虑过开发(我的第一个)软件包的可能性。但是我遇到了 Lemon Graph C++ 代码以这种方式调用标题的问题(例如):

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

所以这意味着(至少我相信这一点)我无法避免安装 Lemon Graph Library。如果我想制作 Lemon Graph Library 的 R 包,我必须再次“重写”所有代码!!!所以这不是我的主要选择。

最好的问候

【问题讨论】:

标签: r module inline rcpp lemon-graph-library


【解决方案1】:

我已经成功解决了这个问题。 Here你可以找到我所做的详细解释。也许,这对这里的大多数人来说是微不足道的,但对于与我处于同一位置的人来说,这可能是一个很好的起点。我将在这里发布我所做的简历。

首先我安装了 Lemon Graph (C++) Library (LGL)。我刚刚从其主页 (from here) 下载了 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

所以,通过这种方式,我刚刚创建了一个新的基于 Rcpp 的源包,名为 pkgwithlgl。现在在 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包?

最好的问候

【讨论】:

  • 对不起我的英语。最好的问候
  • 在您展示的示例中,仍然无法使用/引用 R 中的图形对象。
【解决方案2】:

您好,感谢您对Rcpp 的关注。

要在不同库函数之间绑定调用,您可能需要考虑构建一个包。现在有 20 个使用 Rcpp 的包,如 on the Rcpp page on CRAN 所列,因此您可以从中复制示例。乍一看,。这与编写普通程序没有什么不同,而 Rcpp 只是帮助你将它传递给 R。

如果您有更多问题,请随时将它们带到rcpp-devel 列表中。

【讨论】:

  • @Jeremiah Willcock:我必须更仔细地查看您的答案。但乍一看,这不是我需要的,因为它是 R 代码。我使用计算量大的模型(我是物理学家)。换句话说,我需要在 C++(可能是 C)中实现一些功能。 R 对其他一切都很好,所以我非常喜欢在 R 中集成 C++ 代码。感谢您的回复。 @Dirk Eddelbuettel:我会看看如何在 R 中构建一个包。但是如果我构建一个包,它将依赖于 Lemon Graph Library,那么如果有人想使用&gt;install.package() 安装它,它将无法工作。我是对的?
  • @J.I.Perotti :查看手册编写 R 扩展 (cran.r-project.org/doc/manuals/R-exts.pdf) 他们解释了如何使用依赖项等。它要求有点习惯,但最终它非常简单。所以简而言之:对其他包的依赖不一定是问题,大多数包都以一种或另一种方式依赖于其他包。
  • @Every-one 我正在研究和使用示例以构建通过 Rcpp 集成 C++ 代码的包,但我需要时间。我只想说,考虑到你的建议。最好的问候。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-06-13
相关资源
最近更新 更多