Библиотека графов лимонов на R с использованием Rcpp - PullRequest
3 голосов
/ 07 февраля 2011

Я думаю, что этот ответ немного сложен, потому что включает в себя несколько вещей.

Я хочу сделать высокопроизводительные вычисления с R, особенно с графиками (сетями).Как пакет R igraph очень приятно.Но R медленный, поэтому я хочу кодировать вычислительно дорогие процедуры на C ++ (возможно, на C).Я взглянул на библиотеку igraph C, и мне было немного грязно с ней работать.Я также смотрю на Boost Graph Library и читаю о ней, которую трудно изучить.В итоге я нашел Библиотека графов лимонов .Он написан на C ++ и, кажется, с ним очень приятно работать.

Поэтому я установил Lemon Graph Library, как рекомендовано на официальной странице.Затем, используя встроенные пакеты Rcpp и inline , я запускаю код Lemon Graph C ++ из 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")

в файл 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 ()?

В принципе: я не могу понять, как вызвать функцию C ++, встроенную в R, из другой функции C ++ такжевстроено в R. Возможно ли это?Есть ли другой способ, который не использует встроенный код?

Может быть, я могу сделать это с помощью Rcpp модулей , но я не мог (до сих пор) понять, как это сделать.У меня проблемы с работой модулей.Я буду продолжать пытаться с этим, но, возможно, я могу получить здесь какую-то подсказку.

Я также подумал о возможности разработки (моего первого) пакета.Но у меня была проблема с тем, что код Lemon Graph C ++ вызывает заголовки следующим образом (например):

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

Так что это означает (по крайней мере, я так считаю), что я не могу избежать установкиБиблиотека графов лимонов.Если я хочу сделать пакет R библиотеки Lemon Graph Library, я должен снова «переписать» весь код !!!Так что это не мой основной вариант.

С наилучшими пожеланиями

Ответы [ 2 ]

2 голосов
/ 11 февраля 2011

Мне удалось успешно решить эту проблему. Здесь вы можете найти подробное объяснение того, что я сделал.Может быть, это тривиально для большинства людей здесь, но это может быть хорошей отправной точкой для кого-то, кто находится в том же положении, что и я.Здесь я опубликую резюме того, что я сделал.

Сначала я установил библиотеку Lemon Graph (C ++) (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.

Так что все работает.Теперь идея состоит в том, чтобы интегрировать этот код в R через Rcpp.Итак, в каком-то каталоге я открываю консоль 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?

С наилучшими пожеланиями

1 голос
/ 07 февраля 2011

Привет, и спасибо за ваш интерес к Rcpp .

Чтобы связать вызовы между различными библиотечными функциями, возможно, вы захотите разобраться в создании пакета. Теперь существует двадцать пакетов, использующих Rcpp, как указано на странице Rcpp в CRAN , поэтому у вас есть примеры для копирования. При первом одобрении. это ничем не отличается от написания обычной программы , а Rcpp просто помогает вам получить его до R.

Если у вас есть дополнительные вопросы, не стесняйтесь вносить их в список rcpp-devel.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...