void mergePartition(std::vector<int>& V, int start, int mid, int end){ int itr1 = start; int itr2 = mid+1; int itr3 = 0; std::vector<int> Vout(end-start+1); while( itr1 <= mid && itr2 <= end){ if(V[itr1] <= V[itr2]){ Vout[itr3++] = V[itr1++]; }else{ Vout[itr3++] = V[itr2++]; } } if(itr1 > mid){ for(int i=itr2; i <= end; ++i) Vout[itr3++] = V[i]; } else { for(int i=itr1; i <= mid; ++i) Vout[itr3++] = V[i]; } std::copy(Vout.begin(), Vout.end(), V.begin()+start); }
//' @title Master Wrapper for the GMWM Estimator //' @description This function generates WV, GMWM Estimator, and an initial test estimate. //' @param data A \code{vec} containing the data. //' @param theta A \code{vec} with dimensions N x 1 that contains user-supplied initial values for parameters //' @param desc A \code{vector<string>} indicating the models that should be considered. //' @param objdesc A \code{field<vec>} containing a list of parameters (e.g. AR(1) = c(1,1), ARMA(p,q) = c(p,q,1)) //' @param model_type A \code{string} that represents the model transformation //' @param starting A \code{bool} that indicates whether the supplied values are guessed (T) or are user-based (F). //' @param alpha A \code{double} that handles the alpha level of the confidence interval (1-alpha)*100 //' @param compute_v A \code{string} that describes what kind of covariance matrix should be computed. //' @param K An \code{int} that controls how many times theta is updated. //' @param H An \code{int} that controls how many bootstrap replications are done. //' @param G An \code{int} that controls how many guesses at different parameters are made. //' @param robust A \code{bool} that indicates whether the estimation should be robust or not. //' @param eff A \code{double} that specifies the amount of efficiency required by the robust estimator. //' @return A \code{field<mat>} that contains a list of ever-changing estimates... //' @author JJB //' @references Wavelet variance based estimation for composite stochastic processes, S. Guerrier and Robust Inference for Time Series Models: a Wavelet-Based Framework, S. Guerrier //' @keywords internal //' @export //' @backref src/gmwm_logic.cpp //' @backref src/gmwm_logic.h // [[Rcpp::export]] arma::field<arma::mat> gmwm_master_cpp(arma::vec& data, arma::vec theta, const std::vector<std::string>& desc, const arma::field<arma::vec>& objdesc, std::string model_type, bool starting, double alpha, std::string compute_v, unsigned int K, unsigned int H, unsigned int G, bool robust, double eff){ // Obtain counts of the different models we need to work with std::map<std::string, int> models = count_models(desc); // HACK METHOD (todo: formalize it) // Determine if we need to difference if(models["SARIMA"] > 0){ // Note: s, i, si are 6,7,8 => 5,6,7 for(unsigned int i = 0; i < desc.size(); i ++){ if(objdesc(i).n_elem > 3){ arma::vec sarima_desc = objdesc(i); // Do we need to difference? if(sarima_desc(6) > 0 || sarima_desc(7) > 0){ // Perform differencing in specific order... // First non-seasonal and then seasonal. if(sarima_desc(6) > 0){ // Lag is always 1, number of differences is (i) data = diff_cpp(data, 1, sarima_desc(6)); } if(sarima_desc(7) > 0){ // Lag is always seasonality (s) and differences is (si). data = diff_cpp(data, sarima_desc(5), sarima_desc(7)); } // Kill loop. We only handle the tsmodel object with the first difference. break; } } } } // ------ Variable Declarations // Length of the Time Series unsigned int N = data.n_elem; // Number of Scales (J) unsigned int nlevels = floor(log2(N)); // Number of parameters unsigned int np = theta.n_elem; // Take the mean of the first difference double expect_diff = mean_diff(data); // Guessed values of Theta (user supplied or generated) arma::vec guessed_theta = theta; // MODWT decomp arma::field<arma::vec> modwt_decomp = modwt_cpp(data, "haar", nlevels, "periodic", true); // Obtain WV and confidence intervals arma::mat wvar = wvar_cpp(modwt_decomp, robust, eff, alpha, "eta3"); // Extract arma::vec wv_empir = wvar.col(0); arma::vec ci_lo = wvar.col(1); arma::vec ci_hi = wvar.col(2); //------------------------- // Obtain Covariance Matrix //------------------------- arma::mat V; // compute_cov_cpp is the hard core function. It can only be improved by using parallelization. if(compute_v == "diag" || compute_v == "full"){ arma::field<arma::mat> Vout = compute_cov_cpp(modwt_decomp, nlevels, compute_v, robust, eff); if(robust){ V = Vout(1); }else{ V = Vout(0); } }else{ V = fast_cov_cpp(wvar.col(2), wvar.col(1)); } // Obtain the Omega matrix arma::mat omega = arma::inv(diagmat(V)); // Store the original V matrix (in case of bootstrapping) for use in the update function arma::mat orgV = V; // Calculate the values of the Scales arma::vec scales = scales_cpp(nlevels); // Min-Max / N double ranged = dr_slope(data); // Guess starting values for the theta parameters if(starting){ // Always run guessing algorithm theta = guess_initial(desc, objdesc, model_type, np, expect_diff, N, wvar, scales, ranged, G); // If under ARMA case and only ARMA is in the model, // then see how well these values are. if(desc.size() == 1 && (desc[0] == "SARIMA" || desc[0] == "ARMA11") && N <= 1000){ // Use R's ARIMA function to estimate parameter space arma::vec theta2 = Rcpp_ARIMA(data, objdesc(0)); // Only 1 objdesc in the available. // Obtain the obj function under omega with these initial guesses // DO >>NOT<< USE Yannick's to optimize starting values!!!! double mle_css_obj = getObjFun(theta2, desc, objdesc, model_type, omega, wv_empir, scales); // Obtain the objective function under Yannick's starting algorithm double init_guess_obj = getObjFunStarting(theta, desc, objdesc, model_type, wv_empir, scales); // What performs better? if(mle_css_obj < init_guess_obj){ // Disable starting value optimization if using MLE. theta = theta2; starting = false; } } guessed_theta = theta; } // Obtain the GMWM estimator's estimates. theta = gmwm_engine(theta, desc, objdesc, model_type, wv_empir, omega, scales, starting); // Optim may return a very small value. In this case, instead of saying its zero (yielding a transform issue), make it EPSILON. theta = code_zero(theta); // Enable bootstrapping if(compute_v == "bootstrap"){ for(unsigned int k = 0; k < K; k++){ // Create the full V matrix V = cov_bootstrapper(theta, desc, objdesc, N, robust, eff, H, false); // Update the omega matrix omega = arma::inv(diagmat(V)); // The theta update in this case MUST not use Yannick's starting algorithm. Hence, the false value. theta = gmwm_engine(theta, desc, objdesc, model_type, wv_empir, omega, scales, false); // Optim may return a very small value. In this case, instead of saying its zero (yielding a transform issue), make it EPSILON. theta = code_zero(theta); } } if(desc[0] == "SARIMA" && desc.size() == 1){ arma::vec temp = objdesc(0); unsigned int p = temp(0); if(p != 0 && invert_check(arma::join_cols(arma::ones<arma::vec>(1), -theta.rows(0, p - 1))) == false){ Rcpp::Rcout << "WARNING: This ARMA model contains AR coefficients that are NON-STATIONARY!" << std::endl; } } // Order AR1s / GM so largest phi is first! if(models["AR1"] > 1 || models["GM"] > 1){ theta = order_AR1s(theta, desc, objdesc); } // Obtain the objective value function arma::vec obj_value(1); obj_value(0) = getObjFun(theta, desc, objdesc, model_type, omega, wv_empir, scales); arma::vec dr_s(1); dr_s(0) = ranged; // Decomposition of the WV. arma::mat decomp_theo = decomp_theoretical_wv(theta, desc, objdesc, scales); arma::vec theo = decomp_to_theo_wv(decomp_theo); // Export information back arma::field<arma::mat> out(13); out(0) = theta; out(1) = guessed_theta; out(2) = wv_empir; out(3) = ci_lo; out(4) = ci_hi; out(5) = V; out(6) = orgV; out(7) = expect_diff; out(8) = theo; out(9) = decomp_theo; out(10) = obj_value; out(11) = omega; out(12) = dr_s; return out; }
int main() { char powerfile[]="Power.txt"; GetPower(powerfile); /* * 声明核中的变量 */ std::vector<double> Vcore; std::vector<double> Rcore; //std::vector<double> ecore;//核的热容中的电流源部分 //std::vector<double> rcore;//核的热容中的热阻部分 //std::vector<double> Ipoint; /* * 声明基底中的变量 */ double Vbase(Tamb); double Ibase; double Rbase((r_conduct+r_fan)/A);//初始化基底的热阻,/@param A表示从密度换算 double ebase(0); double rbase(h/(2*(c_conduct*A)));//初始化基底的热容中的热阻部分=@param h/2@param c,*@param A表示从密度换算 /* * 初始化基底中的@param Vbase和@param ebase */ for(int i=0;i<CoreNumber;i++) { Rcore.push_back(r_bulk/Acore.at(i));//初始化核中的热阻,/@param Acore表示从密度换算 } /* * 初始化核中的@param Vcore和@param ecore */ for(int i=0;i<CoreNumber;i++) { Vcore.push_back(Tamb); //rcore.push_back(h/(2*(c_bulk*Acore.at(i))));//初始化@param rcore=@param h/2@param c,*@param Acore表示从密度换算 //ecore.push_back(0); } /* * 二级等效电路中,计算热阻和热容热阻部分的等效值 */ std::vector<double> r; for(int i=0;i<CoreNumber;i++) { r.push_back(Rcore.at(i));//计算等效值 } double rtmp=r.at(0);//用来计算@param Vbase的临时变量,是所有@param rcore的并联值 double Itmp(0); /* * 计算@param Vbase时用到的热阻并联和 */ for(int i=0;i<CoreNumber-1;i++) { rtmp=Pararlle(rtmp,r.at(i+1));//计算并联值 } rtmp=Pararlle(rtmp,Pararlle(Rbase,rbase));//与@param Rbase并联 /* * @brief 打开输出文件,并相应的打印表头 * 主要的输出内容:@param Vore、@param Pcore、@param Vbase、@param compareVbase */ std::ofstream Vout("Vcore.txt"); std::ofstream Pout("Pcore.txt"); std::ofstream Bout("Base.txt"); if(not Vout) std::perror("Vcore.txt"); if(not Bout) std::perror("Pcore.txt"); if(not Pout) std::perror("Base.txt"); Vout.precision(SetPrecision); Bout.precision(SetPrecision); Pout.precision(SetPrecision); for(int i=0;i<CoreNumber;i++) Pout<<std::setw(SetWidth)<<std::right<<"Pcore("<<i+1<<")"; Pout<<"\n"; for(int i=0;i<CoreNumber;i++) Vout<<std::setw(SetWidth)<<std::right<<"Vcore("<<i+1<<")"; Vout<<std::endl; Bout<<std::setw(SetWidth)<<"R(bc)Cb="<<Pararlle(Rbase,Rcore[0])*c_conduct<<"\n"; Bout<<std::setw(SetWidth)<<"VBase"; Bout<<std::setw(SetWidth)<<"Charge"<<"\n"; std::vector<double> Vref; std::vector<double> newPower; for(int i=0;i<CoreNumber;i++) { Vref.push_back(Vcore.at(i)); newPower.push_back(CorePower.at(i)); } double eps(1); double compareVbase(0); do { for(std::vector<double>::iterator i=Vcore.begin();i!=Vcore.end();i++) Vout<<std::setw(SetWidth)<<*i+amb<<"\t"; Vout<<std::endl; for(std::vector<double>::iterator i=newPower.begin();i!=newPower.end();i++) Pout<<std::setw(SetWidth)<<*i; Pout<<"\n"; Bout<<std::setw(SetWidth)<<Vbase; Bout<<std::setw(SetWidth)<<compareVbase<<"\n"; for(int i=0;i<CoreNumber;i++) { Vref.at(i)=Vcore.at(i); } /* * 刷新@param Vbase以及@param ebase */ Itmp=0;//用来计算@param Vbase的临时变量,是所有核内电流的和 for(int j=0;j<CoreNumber;j++) { newPower.at(j)=CorePower.at(j)+LeakagePower(Vcore.at(j));//刷新实际的功耗值(密度)=源功耗+漏电流功耗 //Ipoint.at(j)=(newPower.at(j)*rcore.at(j)/r.at(j)); Itmp+=newPower.at(j);//计算@param Itmp,需要每次刷新 } Itmp+=ebase; /* * 刷新@param Vcore,@param Vbase的值 */ Vbase=rtmp*Itmp; double SumNewPower=0;//计算所有核的实际功耗总值,用以计算稳定@param Vcore以及充电曲线中的@param Vbase for(int i=0;i<CoreNumber;i++) { SumNewPower+=newPower.at(i); } compareVbase=ChargeLine(SumNewPower,Rbase,c_conduct*A,IterNumber++);//注意:@param Cbase=@param c_conduct*@param A for(int i=0;i<CoreNumber;i++) { Vcore.at(i)=Vbase+newPower.at(i)*Rcore.at(i); } /* * 刷新@param Ibase,@param ebase的值 */ Ibase=0; for(int i=0;i<CoreNumber;i++) { Ibase+=(Vcore.at(i)-Vbase)/Rcore.at(i); } Ibase+=-Vbase/Rbase; ebase=Vbase/rbase+Ibase;//计算@param ebase,需要每次刷新 /* * 根据@param eps(@param Icore的前后迭代差)判断迭代的收敛情况 */ eps=0; for(int i=0;i<CoreNumber;i++) { Vref.at(i)=std::fabs(Vref.at(i)-Vcore.at(i)); eps=std::max(Vref.at(i),eps); } }while(std::fabs(eps)>0.000001); std::vector<double> Vstable=StableVcore(newPower,Rcore,Rbase);//@param Vstable看作是理论稳定温度 注意:计算中用的是新的稳定后的功耗向量 char charVstable[]="Vstable"; DisplayVector(Vstable,charVstable);//输出稳定温度值用来对比而已(打开Vstable.txt) Vout.close(); Bout.close(); Pout.close(); return 0; }