Как преобразовать R в C++ для Rcpp

Следующий фрагмент кода 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;
}")

Переписывание кода R на C++. adv-r.hadley.nz/rcpp.html. Это может помочь вам

Peter Chung 10.10.2022 09:37

@PeterChung Это то, на что я смотрел в дополнение к аналогичному фрагменту C++, который у меня был раньше. Я обновил свой прогресс, но он не работает. Можете ли вы хотя бы проверить мое обновление, если я делаю какие-то очевидные ошибки?

Rel_Ai 10.10.2022 09:58
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
2
102
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

В вашем коде 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 10.10.2022 11:29

@Rel_Ai Я внес небольшую корректировку. Теперь кажется, что результаты совпадают, учитывая одно и то же случайное начальное число.

Allan Cameron 10.10.2022 11:46

Вы буквально спасли мой день. Это отличное решение и очень быстрое менее чем за секунду по сравнению с 3+ минутами для данной проблемы.

Rel_Ai 10.10.2022 11:57

Еще один прекрасный ответ от @AllanCameron! Проголосовал и спасибо!

Dirk Eddelbuettel 10.10.2022 15:00

@AllanCameron Я внес небольшую поправку в ваш код, чтобы он соответствовал моим потребностям. Кажется, что это компилируется, но когда я пытаюсь запустить его со значениями, сеанс R полностью завершается, говоря, что произошла фатальная ошибка. Я добавил адаптированный код в вопрос, не могли бы вы изучить это? Это проблема с моей настройкой или проблема не зависит от самой кодировки?

Rel_Ai 13.10.2022 20:33

Другие вопросы по теме