2016-04-11 35 views
0
ile değiştiriliyor

RcppArmadillo kullanarak tam döndürme ile LU ayrıştırma gerçekleştirmeye çalışıyorum. Neyse ki ben istediğimi yapar this Matlab kodu var, ama ben Armadillo için dönüştürme bazı zorluklar yaşıyorum. Girdileri RcppArmadillo

Sana girişi L, U ve P ve arma::LU fonksiyon L U ve P

dönen yerine girilir L, U ve P matrisleri değiştiren arma::LU gibi benim gecpLU fonksiyon iş yapmak istedim

normal Rcpp ile bu kadar gibi kolayca girişlerini modifiye biliyoruz:

NumericVector example(NumericVector X) { 
    X = 2 * X; 
    return X; 
} 

Bu bir vektör iki kez girdi dönün ve aynı zamanda eşit iki kere orijinal değerine girişi değiştirecektir. Ancak, bunun RcppArmadillo için işe yaramayacağını çabucak keşfettim.

arma::colvec example(arma::colvec X) { 
    X = 2 * X; 
    return X; 
} 

Ben R maruz kaldığında arma nesneler R kopyaları böylece doğrudan R nesneyi değiştiremez nesneler, çünkü bu, bir giriş değişmeyecek anlıyorum, ama yine de olması gerektiği gibi hissediyorum şöyle Armadillo'nun LU gibi bir işlev yazabilir:

#include <RcppArmadillo.h> 
using namespace Rcpp; 
// [[Rcpp::depends(RcppArmadillo)]] 
int gecpLU(arma::mat L, arma::mat U, arma::mat P, arma::mat Q, arma::mat A) { 
    // Take A and overwrite LUPQ such that A=P*L*U*Q 
    int n=A.n_rows; 
    P.eye(n,n); 
    Q.eye(n,n); 
    arma::mat AA=A; 
    // for (int i=0;i<(n-1);i++) { 
    // delete a whole bunch of stuff not relevant to question 
    // } 
    L.eye(n,n); 
    arma::mat tempmat=arma::trimatl(AA); 
    tempmat.diag()*=0; 
    L=L-tempmat; 
    U=arma::trimatu(AA); 

    return 0; 
} 

// [[Rcpp::export]] 
List test(arma::mat A) { 
    arma::mat L1,U1,P1,L2,U2,P2,Q; 
    arma::lu(L1,U1,P1,A); 
    gecpLU(L2,U2,P2,Q,A); 
    return List::create(_["L1"]=L1, 
         _["U1"]=U1, 
         _["P1"]=P1, 
         _["L2"]=L2, 
         _["U2"]=U2, 
         _["P2"]=P2, 
         _["Q"]=Q); 
} 

Bu durumda, benim gecpLU işlevine R matrisleri geçirerek etmiyorum, ama arma::mat yüzden girişlerini değiştirmek mümkün olmalıdır.

test'u çalıştırdığımda, L1, U1 ve P1 için matrisler elde ediyorum, ancak L2, U2, P2 ve Q için 0x0 matrisleri var. Bir şeyi yanlış anlamam gerekir gibi hissediyorum. RcppArmadillo ile girdileri değiştirmek mümkün mü? Eğer değilse 4 matris çıktı almak için en iyi yolu nedir? Bir liste? Altında

+2

basit şekilde aktarmak için (diğer bir deyişle sonunda nesne yok) kopya geçmek Rcpp vektörleri ve yardımcı kurucuları kullanarak 'arma' nesneleri oluşturun (daha fazla bilgi için http://arma.sourceforge.net/docs.html#Col adresindeki 'Gelişmiş yapıcılar 'bölümlerine bakın). –

cevap

2

:

int gecpLU(arma::mat L, arma::mat U, arma::mat P, arma::mat Q, arma::mat A) 

Onların yok edilir işlevi sonunda daha sonra bu matrislerin her yeni kopyalarını oluşturup edilir.

Beklediğiniz şey, nesnenin değiştirilmiş olmasıdır. Bunu yapmak için, nesne türünün sonuna bir & eklemeniz gerekir, böylece derleyici nesnenin başvurusunu almayı bilir.

void gecpLU(arma::mat& L, arma::mat& U, arma::mat& P, arma::mat& Q, arma::mat& A) 

Not, ben de void için int den gecpLU dönüş türünü değiştirdi. Bakınız:

#include <RcppArmadillo.h> 
using namespace Rcpp; 
// [[Rcpp::depends(RcppArmadillo)]] 
void gecpLU(arma::mat& L, arma::mat& U, arma::mat& P, arma::mat& Q, arma::mat& A) { 
    // Take A and overwrite LUPQ such that A=P*L*U*Q 
    int n=A.n_rows; 
    P.eye(n,n); 
    Q.eye(n,n); 
    arma::mat AA=A; 
    // for (int i=0;i<(n-1);i++) { 
    // delete a whole bunch of stuff not relevant to question 
    // } 
    L.eye(n,n); 
    arma::mat tempmat=arma::trimatl(AA); 
    tempmat.diag()*=0; 
    L=L-tempmat; 
    U=arma::trimatu(AA); 
} 

// [[Rcpp::export]] 
List test(arma::mat A) { 
    arma::mat L1,U1,P1,L2,U2,P2,Q; 
    arma::lu(L1,U1,P1,A); 
    gecpLU(L2,U2,P2,Q,A); 
    return List::create(_["L1"]=L1, 
         _["U1"]=U1, 
         _["P1"]=P1, 
         _["L2"]=L2, 
         _["U2"]=U2, 
         _["P2"]=P2, 
         _["Q"]=Q); 
} 

basit geçici örneği (bu değişiklik sağlar), referans ile bu geçiş göstermek için genel

#include <RcppArmadillo.h> 
// [[Rcpp::depends(RcppArmadillo)]] 
using namespace Rcpp; 

void reference_obj(arma::vec& y){ 
    y.fill(1); 
} 

void copy_obj(arma::vec y){ 
    y.fill(0); 
} 

// [[Rcpp::export]] 
arma::vec on_reference_mod(arma::vec x) { 

    reference_obj(x); 

    return x; 
} 


// [[Rcpp::export]] 
arma::vec on_copy_mod(arma::vec x) { 

    copy_obj(x); 

    return x; 
} 

/*** R 
# Should get a vector of 1's 
on_reference_mod(1:10) 

# Should get a vector of 1:10 
on_copy_mod(1:10) 
*/ 
+0

Teşekkürler! Bir şey kaçırdığımı biliyordum. – Carl