Следующий фрагмент кода R очень неэффективен с точки зрения скорости, и мне нужно, чтобы он был значительно быстрее, так как в исходной задаче length(dt) довольно большой.
Можете ли вы помочь мне преобразовать следующий фрагмент кода R в C++, чтобы использовать функцию RCPP в R? Мои знания C++ очень близки к 0 и я не могу понять, как сделать преобразование.
inity <- 0
cumy <- rep(0,length = length(dt))
dec.index <- 1
startingPoint <- 2
temp <- numeric()
repFlag <- F
for (i in 2:length(dt)){
cumy[i] <- inity + rgamma(n = 1, shape = a*timedt, scale = b)
inity <- cumy[i]
if (dt[i] %in% decPoints){
if (dt[i] %in% LTset){
repFlag <- ifelse(cumy[i] >= LP, T, F)
} else if (dt[i] %in% MainMDset && repFlag == T){
genRanProb <- rbinom(1,1,(1-p1))
cumy[i] <- inity*genRanProb
inity <- cumy[i]
} else if (dt[i] %in% ProbMDset && repFlag == T){
genRanProb <- rbinom(1,1,pA)
cumy[i] <- inity*genRanProb
inity <- cumy[i]
}
}
}
Если вы хотите запустить код, вы можете использовать следующие значения:
a <- 0.2
b <- 1
ph <- 1000
timedt <- 1
oppInt <- 90
dt <- seq(0,ph,timedt)
LT <- 30
MainMDset <- seq(oppInt, ph, oppInt)
ProbMDset <- c(0,seq((oppInt + oppInt/2), ph, oppInt))
LTset <- sort(c(ProbMDset, MainMDset))
LTset <- LTset - LT
decPoints <- sort(c(LTset, ProbMDset, MainMDset))
decPoints <- decPoints[-which(decPoints < 0)]
decPoints[1] <- 1
p1 <- 0
pA <- 0.5
LP <- 40
Код для последующего вопроса:
Rcpp::cppFunction("
NumericVector cumyRes(double a, double b, double timedt, NumericVector dt,
NumericVector ProbMDset, NumericVector MainMDset,
NumericVector decPoints, double LP, double LT,
double p1, double pA, int ii, double x1, double x2){
bool repFlag = false;
int n = dt.size();
double inity = 0;
NumericVector out(n);
std::unordered_set<double> sampleSetMd(MainMDset.begin(), MainMDset.end());
std::unordered_set<double> sampleSetProb(ProbMDset.begin(), ProbMDset.end());
std::unordered_set<double> sampleSetDec(decPoints.begin(), decPoints.end());
for (int i = 1; i < n; ++i){
ii = ii + 1;
double d = dt[ii];
out[ii] = inity + rgamma(1, a * timedt, b)[0];
inity = out[ii];
if (sampleSetDec.find(d) != sampleSetDec.end()) {
if (sampleSetProb.find(d + LT) != sampleSetProb.end() ||
sampleSetMd.find(d + LT) != sampleSetMd.end()) {
repFlag = inity >= LP;
} else if (sampleSetMd.find(d) != sampleSetMd.end() && repFlag) {
double genRanProb = rbinom(1, 1, (1 - p1))[0];
for (int j = ii; ii < (ii+10); ++j){
out[j] = inity * genRanProb;
}
inity = inity * genRanProb;
ii = ii + x1 - 1;
} else if (sampleSetProb.find(d) != sampleSetProb.end() && repFlag) {
double genRanProb = rbinom(1, 1, pA)[0];
for (int j = ii; ii < (ii+5); ++j){
out[j] = inity * genRanProb;
}
inity = inity * genRanProb;
ii = ii + x2 - 1;
}}}
return out;
}")
@PeterChung Это то, на что я смотрел в дополнение к аналогичному фрагменту C++, который у меня был раньше. Я обновил свой прогресс, но он не работает. Можете ли вы хотя бы проверить мое обновление, если я делаю какие-то очевидные ошибки?





В вашем коде C++ есть несколько ошибок, вероятно, слишком много, чтобы перечислить их в кратком ответе. Однако следующие исправления, похоже, следуют вашей логике и компилируются, чтобы дать аналогичные ответы на ваш цикл R за меньшее время:
Rcpp::cppFunction("
NumericVector cumyRes(double a, double b, double timedt, NumericVector dt,
NumericVector ProbMDset, NumericVector MainMDset,
NumericVector decPoints, double LP, double LT,
double p1, double pA){
bool repFlag = false;
int n = dt.size();
double inity = 0;
NumericVector out(n);
std::unordered_set<double> sampleSetMd(MainMDset.begin(), MainMDset.end());
std::unordered_set<double> sampleSetProb(ProbMDset.begin(), ProbMDset.end());
std::unordered_set<double> sampleSetDec(decPoints.begin(), decPoints.end());
for (int i = 1; i < n; ++i){
double d = dt[i];
out[i] = inity + rgamma(1, a * timedt, b)[0];
inity = out[i];
if (sampleSetDec.find(d) != sampleSetDec.end()) {
if (sampleSetProb.find(d + LT) != sampleSetProb.end() ||
sampleSetMd.find(d + LT) != sampleSetMd.end()) {
repFlag = inity >= LP;
} else if (sampleSetMd.find(d) != sampleSetMd.end() && repFlag) {
double genRanProb = rbinom(1, 1, (1 - p1))[0];
out[i] = inity * genRanProb;
inity = out[i];
} else if (sampleSetProb.find(d) != sampleSetProb.end() && repFlag) {
double genRanProb = rbinom(1, 1, pA)[0];
out[i] = inity * genRanProb;
inity = out[i];
}}}
return out;
}")
Вы можете проверить это с помощью:
cumyRes(a, b, timedt, dt, ProbMDset, MainMDset, decPoints, LP, LT, p1, pA)
Сравнивается ли тест с предоставленным мной решением R? Я использовал set.seed() для запуска с одинаковыми параметрами, и они разные. Самое главное, out[i] всегда увеличивается без условного сброса, как это делается в фактическом решении R.
@Rel_Ai Я внес небольшую корректировку. Теперь кажется, что результаты совпадают, учитывая одно и то же случайное начальное число.
Вы буквально спасли мой день. Это отличное решение и очень быстрое менее чем за секунду по сравнению с 3+ минутами для данной проблемы.
Еще один прекрасный ответ от @AllanCameron! Проголосовал и спасибо!
@AllanCameron Я внес небольшую поправку в ваш код, чтобы он соответствовал моим потребностям. Кажется, что это компилируется, но когда я пытаюсь запустить его со значениями, сеанс R полностью завершается, говоря, что произошла фатальная ошибка. Я добавил адаптированный код в вопрос, не могли бы вы изучить это? Это проблема с моей настройкой или проблема не зависит от самой кодировки?
Переписывание кода R на C++. adv-r.hadley.nz/rcpp.html. Это может помочь вам