Вычисление собственных значений в кодах C-внутри-R

Я пишу код R, который использует скомпилированный код C.

Из документа «Написание расширений R» я узнал, что существует множество исполняемых файлов / DLL R, которые можно вызывать из кода C. Заголовочный файл 'Rmath.h' перечисляет многие доступные функции, а его исходные коды перечислены на этом веб-сайте: http://svn.r-project.org/R/trunk/src/nmath/

Мне нужно вычислить разложение по сингулярным значениям многих матриц, однако я не нашел подпрограмм, которые делают это на указанном выше веб-сайте. (Итак, я предполагаю, что Rmath.h не содержит подпрограмм SVD) Есть ли простой способ выполнить вычисления собственных значений в коде C-внутри-R?

Большое тебе спасибо.


person FairyOnIce    schedule 04.01.2013    source источник
comment
Почему вы хотите использовать svd для вычисления собственных значений?   -  person David Heffernan    schedule 05.01.2013


Ответы (2)


Если вы готовы использовать Rcpp и связанные с ним пакеты, существующие примеры для fastLm() покажут вам, как это сделать с помощью

  • Eigen через RcppEigen
  • Армадилло через Rcpp
  • GSL через RcppGSL

где последние два будут использовать тот же BLAS, что и R, а в Eigen есть что-то внутреннее, что часто может быть быстрее. Все пакеты реализуют lm() с использованием декомпозиции, предлагаемой языком (часто с использованием решения или связанного, но переключиться на SVD несложно, если у вас есть инструментальная цепочка, работающая на вас).

Изменить: вот явный пример. Используйте следующий код C ++:

#include <RcppArmadillo.h>   

// [[Rcpp::depends(RcppArmadillo)]] 

// [[Rcpp::export]]   
arma::vec getEigen(arma::mat M) { 
    return arma::eig_sym(M);      
}    

сохраните в файл «eigenEx.cpp». Тогда все, что нужно, это этот код R:

library(Rcpp)               ## recent version for sourceCpp()
sourceCpp("eigenEx.cpp")    ## converts source file into getEigen() we can call

чтобы мы могли запустить это:

set.seed(42)        
X <- matrix(rnorm(3*3), 3, 3)
Z <- X %*% t(X)              

getEigen(Z)                 ## calls function created above

и я получаю тот же собственный вектор, что и у R. Это действительно не намного проще.

Это также позволяет Armadillo выбирать, какой метод использовать для разложения Eigen, и, как намекнул Дэвид, это что-то более быстрое, чем полномасштабная SVD (см. Документацию Armadillo).

person Dirk Eddelbuettel    schedule 04.01.2013

Вы можете использовать одну из многих доступных библиотек линейной алгебры (Lapack). Здесь есть ссылка, объясняющая, как получить библиотеки Lapack для Windows. GOTOBLAS и ACML бесплатны. MKL также бесплатен для некоммерческого использования. После того, как вы установили библиотеки, вам нужна функция sgesvd (для float) или dgesvd (для double).

Вот пара примеров от Intel о том, как использовать gesvd.

  1. Row Major
  2. Col ​​Major

Если вы используете Linux, ознакомьтесь с GNU SL и Eigen. Эти библиотеки обычно можно установить из диспетчера пакетов дистрибутива.

person Pavan Yalamanchili    schedule 04.01.2013
comment
Паван: Все верно, все не имеет значения, поскольку ThePricess хочет работать из R, а не из командной строки. - person Dirk Eddelbuettel; 05.01.2013
comment
@DirkEddelbuettel ThePirncess ответил на этот вопрос, когда я узнал, что существует множество исполняемых файлов / DLL R, которые можно вызвать из кода C. Итак, я предположил, что она в конечном итоге захотела иметь разложения в C, а не в R. - person Pavan Yalamanchili; 05.01.2013
comment
В этом случае ThePrincess будет неправильным / сбитым с толку, поскольку этот заголовок НЕ предназначен для внешнего использования программами C. Кроме того, это не требование C-within-R, поэтому я думаю, что мое чтение ближе, чем ваше. - person Dirk Eddelbuettel; 05.01.2013
comment
Я не работаю в командной строке R. Извините за путаницу. Мне нужен результат разложения на C. Я хотел избежать использования Rcpp, потому что это потребовало бы от меня изменения значительной части моих кодов C. - person FairyOnIce; 05.01.2013
comment
Никто не заставляет вас отказываться от соглашений о Си или Си. Но вы получаете и отправляете данные с НАМНОГО меньше кода, используя Rcpp, и ваши надстройки все еще могут быть в стиле C. Твой выбор. - person Dirk Eddelbuettel; 05.01.2013
comment
@ThePrincess просто используйте Rcpp и RcppEigen или RcppGSL только для той части, которая вам нужна svd, сделайте это отдельной функцией / заголовком - person pyCthon; 05.01.2013