我在DNA K-mers计数中工作,我准备这个公式以使用完美哈希表来解决计数:link。 我使用Rcpp API(C ++)将代码集成到R:
中#include <Rcpp.h>
using namespace Rcpp;
/*
this code can be used with c++ by replacing IntegerVector by std::vector<int>
*/
//************************************************
inline const short int V (const char x){
switch(x){
case 'A':case 'a':
return 0;
break;
case 'C':case 'c':
return 1;
break;
case 'G':case 'g':
return 2;
break;
default:
return 3;
break;
}
}
inline unsigned int X0( const std::string A,const int k ,const int n){
unsigned int result=0;
int j=k;
for( int i=n-1;i>n-k-1;i--) {
result+= pow(4,k-j)*V(A[i]);
j--;
}
return result;
}
// [[Rcpp::export]]
inline IntegerVector kmer4(const std::string A,const int n,const int k)
{
IntegerVector P(pow(4,k));
int x=X0(A,k,n);
P[x]++;
const int N=pow(4,k-1);
for( int i=n-k-1;i>-1;i--){
x=N*V(A[i])+x/4-x%4/4;
P[x]++;
}
return P;
}
有两个问题:
假设kmer的索引x,则x的补码为(4 ^ k)-x-1。我们可以使用前面的公式之类的数字运算来反转吗?
运行时有两个问题:迭代字符串和矢量创建,其中k超过8。 是否有解决这些问题的想法?
答案 0 :(得分:0)
第1项:我不熟悉k-mer计数,x
的定义有点不稳定。如果您可以更新您的问题,那么我将尝试解决第1点。但是,对我而言,似乎您只需要使用从基数10转换回基数4的算法?
第2项:是的。正在执行的迭代不是最理想的,因为您经常从string
转换为int
,依此类推。而且,为什么要声明函数inline
?此外,数据传递到A
的数量有多大?
为了解决这个问题,我们将字符串完全移植到std::vector<int>
。实际上,我会说直接将它移植到std::vector<int>
并避免列出它可以切换到非rcpp代码。另外,我们选择使用pass by reference范例而不仅仅是const变量。最后,我减少了inline
声明的数量。
#include <Rcpp.h>
using namespace Rcpp;
//************************************************
inline const short int V (const char x){
switch(x){
case 'A':case 'a':
return 0;
break;
case 'C':case 'c':
return 1;
break;
case 'G':case 'g':
return 2;
break;
default:
return 3;
break;
}
}
std::vector<int> conv_A2V(const std::string & A){
unsigned int obs = A.length()
std::vector<int> out(obs);
for(unsigned int i = 0; i < obs; i++){
out(i) = V(A[i]);
}
return out;
}
unsigned int X0( const std::vector<int> & V_A, const int k, const int n){
unsigned int result=0;
int j=k;
for( int i=n-1;i>n-k-1;i--) {
result+= pow(4,k-j)*V_A[i];
j--;
}
return result;
}
// [[Rcpp::export]]
IntegerVector kmer4(const std::string A, const int n,const int k)
{
// Convert
std::vector<int> V_A = conv_A2V(A);
IntegerVector P(pow(4,k));
int x=X0(V_A,k,n);
P[x]++;
const int N=pow(4,k-1);
for( int i=n-k-1;i>-1;i--){
x=N*V_A[i]+x/4-x%4/4;
P[x]++;
}
return P;
}