void CEquSystem::addVariable(CVariable *pVar, size_t numVar) { auto **ppVar = varPntr() + numVar; if (*ppVar) pVar->setSameVarNextEqu(*(ppVar + nVar())); else *ppVar = pVar; *(ppVar + nVar()) = pVar; }
void CEquSystem::closeVarloop() const { // Make the loop of all appearance of given variable in different equations for (auto i = nVar(); i--;) { auto pVar = variable(i); if (pVar) { auto pVarNextEqu = variable(i + nVar()); pVar->setSameVarNextEqu(pVarNextEqu); while (pVarNextEqu->sameVarNextEqu() != pVar) pVarNextEqu = pVarNextEqu->sameVarNextEqu(); pVar->setSameVarPrevEqu(pVarNextEqu); } } }
//prints all variables and their values void printVars(){ int i=0; while(i < nVar()){ printf("%s = %d\n", vars_ident[i],vars_value[i]); i++; } }
//search for curr_var in the variable array and returns its index //if curr_var is not in the array yet, insert curr_var to the array int findVarIdx(char curr_var[]){ int i,idx=-1; for(i=0;i<nVar();i++){ if(strcmp(curr_var,vars_ident[i])==0){ idx = i; break; } } //if curr_var not in array, add if(idx==-1){ idx = nVar(); strcpy(vars_ident[idx],curr_var); } return idx; }
SGD::SGD() { double tPrev, t, step; rowvec parameter(2), gradient(2), gradientLocal(2), gradientOld(2), nVar(2); double localE; int correlationLength; long idum; writeToFile = false; //-------------------------------------------------------------------------- // MPI int myRank, nNodes; MPI_Comm_size(MPI_COMM_WORLD, &nNodes); MPI_Comm_rank(MPI_COMM_WORLD, &myRank); //-------------------------------------------------------------------------- // Reading data from QD.ini if (myRank == 0) { cout << "Reading configuration from file " << endl; ini INIreader("QD.ini"); McSamples = (int) INIreader.GetDouble("SGD", "McSamples"); importanceSampling = INIreader.GetBool("SGD", "importanceSampling"); thermalization = (int) INIreader.GetDouble("SGD", "thermalization"); SGDSamples = INIreader.GetInt("SGD", "SGDSamples"); dim = INIreader.GetInt("SGD", "dim"); alpha = INIreader.GetDouble("SGD", "alpha"); beta = INIreader.GetDouble("SGD", "beta"); w = INIreader.GetDouble("SGD", "w"); nParticles = INIreader.GetInt("SGD", "nParticles"); m = INIreader.GetInt("SGD", "m"); correlationLength = INIreader.GetInt("SGD", "correlationLength"); usingJastrow = INIreader.GetBool("SGD", "usingJastrow"); writeToFile = INIreader.GetBool("SGD", "writeToFile"); fileName = INIreader.GetString("SGD", "fileName"); fMax = INIreader.GetDouble("SGD", "fMax"); fMin = INIreader.GetDouble("SGD", "fMin"); omega = INIreader.GetDouble("SGD", "omega"); expo = INIreader.GetDouble("SGD", "expo"); A = INIreader.GetDouble("SGD", "A"); a = INIreader.GetDouble("SGD", "a"); maxStep = INIreader.GetDouble("SGD", "maxStep"); } //-------------------------------------------------------------------------- // Broadcasting data to all nodes. if (myRank == 0) cout << "Broadcasting data to nodes." << endl; MPI_Bcast(&McSamples, 1, MPI_INT, 0, MPI_COMM_WORLD); MPI_Bcast(&SGDSamples, 1, MPI_INT, 0, MPI_COMM_WORLD); MPI_Bcast(&importanceSampling, 1, MPI_INT, 0, MPI_COMM_WORLD); MPI_Bcast(&thermalization, 1, MPI_INT, 0, MPI_COMM_WORLD); MPI_Bcast(&dim, 1, MPI_INT, 0, MPI_COMM_WORLD); MPI_Bcast(&alpha, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD); MPI_Bcast(&beta, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD); MPI_Bcast(&w, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD); MPI_Bcast(&nParticles, 1, MPI_INT, 0, MPI_COMM_WORLD); MPI_Bcast(&usingJastrow, 1, MPI_INT, 0, MPI_COMM_WORLD); MPI_Bcast(&m, 1, MPI_INT, 0, MPI_COMM_WORLD); MPI_Bcast(&correlationLength, 1, MPI_INT, 0, MPI_COMM_WORLD); MPI_Bcast(&fMax, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD); MPI_Bcast(&fMin, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD); MPI_Bcast(&omega, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD); MPI_Bcast(&expo, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD); MPI_Bcast(&A, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD); MPI_Bcast(&a, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD); MPI_Bcast(&maxStep, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD); #if 0 cout << "\t A = " << A << "\t a = " << a << "\t maxStep = " << maxStep << "\t expo = " << expo << "\t omega = " << omega << "\t fMin = " << fMin << "\t fMax = " << fMax << endl; #endif //-------------------------------------------------------------------------- //Initializing and thermalizing walkers. if (myRank == 0) cout << "Initializing and thermalizing walkers." << endl; WaveFunction * walker[m]; idum = -1 - myRank - time(NULL); Orbital *orbital = new QDOrbital(dim, alpha, w); Jastrow * jastrow = NULL; if (usingJastrow) jastrow = new QDJastrow(dim, nParticles, beta); Hamiltonian *hamiltonian = new QDHamiltonian(dim, nParticles, w, usingJastrow); WaveFunction *wf = new WaveFunction(dim, nParticles, idum, orbital, jastrow, hamiltonian); // If we are using brute force sampling we have to calculate // the optimal step length. if (!importanceSampling) wf->setOptimalStepLength(); // Thermalizing walker. int k = 0; int thermCorr = m*correlationLength; for (int i = 0; i <= thermalization + thermCorr; i++) { for (int j = 0; j < nParticles; j++) { if (importanceSampling) wf->tryNewPosition(j); else wf->tryNewPositionBF(j); } // Storing walker. if (i > thermalization) { if ((i - thermalization) % (correlationLength) == 0) { if (myRank == 999) cout << "k = " << k << endl; walker[k] = wf->clone(); k++; } } } /* for (int k = 0; k < m; k++) { // Giving each walker a unique seed. idum = -1 - myRank - time(NULL) - k; Orbital *orbital = new QDOrbital(dim, alpha, w); Jastrow * jastrow = NULL; if (usingJastrow) jastrow = new QDJastrow(dim, nParticles, beta); Hamiltonian *hamiltonian = new QDHamiltonian(dim, nParticles, w, usingJastrow); WaveFunction *wf = new WaveFunction(dim, nParticles, idum, orbital, jastrow, hamiltonian); // If we are using brute force sampling we have to calculate // the optimal step length. if (!importanceSampling) wf->setOptimalStepLength(); // Thermalizing walker. for (int i = 0; i < thermalization; i++) { for (int j = 0; j < nParticles; j++) { if (importanceSampling) wf->tryNewPosition(j); else wf->tryNewPositionBF(j); } } // Storing walker. walker[k] = wf; } **/ //-------------------------------------------------------------------------- ofstream outStream; if (myRank == 0) { cout << "Starting minimizing process " << endl; cout << "SGA samples = " << SGDSamples; cout << "\t omega = " << w; cout << "\t alpha_0 = " << alpha; cout << "\t beta_0 = " << beta; cout << endl; outStream.open((const char*) &fileName[0]); // Writing to file outStream << SGDSamples << " " << McSamples << " " << m*nNodes << " " << nParticles << " " << w << endl; } //-------------------------------------------------------------------------- tPrev = 0; parameter(0) = alpha; parameter(1) = beta; nVar(0) = 5; nVar(1) = 5; gradientOld = zeros(1, 2); //-------------------------------------------------------------------------- // Starting SGD algortithm. //-------------------------------------------------------------------------- for (int sample = 1; sample <= SGDSamples; sample++) { // Moving walkers E = 0; accepted = 0; gradient = zeros(1, 2); gradientLocal = zeros(1, 2); for (int i = 0; i < m; i++) { for (int j = 0; j < McSamples; j++) { for (int k = 0; k < nParticles; k++) { if (importanceSampling) { accepted += walker[i]->tryNewPosition(k); } else { accepted += walker[i]->tryNewPositionBF(k); } } localE = walker[i]->sampleEnergy(); E += localE; // / nParticles; gradient += walker[i]->getVariationGradient(); gradientLocal += walker[i]->getVariationGradient() * localE; //} } } //---------------------------------------------------------------------- // Collecting results. MPI_Allreduce(MPI_IN_PLACE, &E, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); MPI_Allreduce(MPI_IN_PLACE, &gradient(0), 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); MPI_Allreduce(MPI_IN_PLACE, &gradient(1), 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); MPI_Allreduce(MPI_IN_PLACE, &gradientLocal(0), 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); MPI_Allreduce(MPI_IN_PLACE, &gradientLocal(1), 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); E /= (nNodes * m * McSamples); gradient /= (nNodes * m * McSamples); gradientLocal /= (nNodes * m * McSamples); // The total variational gradient gradient = 2 * (gradientLocal - gradient * E); //---------------------------------------------------------------------- // Algoritm for the new step length //---------------------------------------------------------------------- double x = -dot(gradient, gradientOld); f = fMin + (fMax - fMin) / (1 - (fMax / fMin) * exp(-x / omega)); t = tPrev + f; if (t < 0) t = 0; //---------------------------------------------------------------------- // Printing progress if (myRank == 0 && sample % 100) { fflush(stdout); cout << "SGA cycle = " << sample << "\t alpha = " << parameter(0) << "\t beta = " << parameter(1) << "\t E = " << E << "\t t = " << t << "\t step = " << step << "\xd"; } //---------------------------------------------------------------------- for (int i = 0; i < 2; i++) { if (gradient(i) * gradientOld(i) < 0) nVar(i)++; // Calulating new step lengths. #if 0 step = gradient(i) * a / pow(nVar(i), expo); if (fabs(step) > maxStep) step *= maxStep / fabs(step); #else // Calculating new step lengths. double gamma = a / pow(t + A, expo); step = gamma * gradient(i); if (fabs(step) > maxStep) step *= maxStep / fabs(step); #endif parameter(i) -= step; // We don't allow negative parameters parameter(i) = abs(parameter(i)); } //---------------------------------------------------------------------- // Setting the new parameters for (int i = 0; i < m; i++) walker[i]->setNewVariationalParameters(parameter(0), parameter(1)); // Writing to file if (myRank == 0) outStream << parameter(0) << " " << parameter(1) << endl; //---------------------------------------------------------------------- // Storing previous values. tPrev = t; gradientOld = gradient; } if (myRank == 0) { cout << endl << "Finished. Ending parameters: " << "\t alpha = " << parameter(0) << "\t beta = " << parameter(1) << "\xd"; //<< endl; outStream.close(); } //-------------------------------------------------------------------------- // Cleaning up //for (int i = 0; i < m; i++) //delete walker[i]; }
Task* create_guessing_task(std::string identifier, Log* log, Stepper* stepper, Wave* varyingWave, Wave* evWave, double tol, size_t nPeriod, size_t showAllIterates, long secvar) { Task* task = new Task ([=]() mutable { varyingWave->lock(); size_t nVar(stepper->n_variables()); size_t nFunc(stepper->n_functions()); double t(stepper->t()); auto f = [nVar,nFunc,stepper,nPeriod,tol,t](const double* x, double* rhs) { stepper->reset(t,x); stepper->advance(nPeriod); for(size_t i(0);i<nVar;++i) rhs[i]=stepper->x()[i]-x[i]; for(size_t i(0);i<nVar*nVar;++i) rhs[i+nVar]=stepper->jac()[i]; // subtract 1 from the diagonal of the Jacobian for(size_t i(0);i<nVar;++i) rhs[nVar+i*(nVar+1)]-=1.0; }; double* x(new double[nVar]); for(size_t i(0);i<nVar;++i) x[i]=varyingWave->data()[i+1]; varyingWave->pop_back(1+nVar+nFunc); bool success(false); try { success=newton(int(nVar),x,f,false,tol); } catch(std::string error) { success=false; log->push<Log::ERROR>(error); } if(!success) { log->push<Log::ERROR>("Newton iteration did not converge\n"); } else { // get eigenvalue and eigenvector info VecD evals,evecs; VecSZ types; double* jac(new double[nVar*nVar]); for(size_t i(0);i<nVar*nVar;++i) jac[i]=stepper->jac()[i]; if(secvar>=0) // in Poincare mode, restore the artificial zero-multiplier to 1 jac[size_t(secvar)*(nVar+1)]=1; floquet(nVar,jac,evals,evecs,types); evWave->push_back(&evals[0],nVar*2); evWave->push_back(&evecs[0],nVar*nVar); for(size_t i(0);i<types.size();++i) evWave->push_back(double(types[i])); delete[] jac; size_t factor(showAllIterates?nPeriod:1); stepper->reset(t,x); for(size_t j(0);j<factor;++j) { try { stepper->advance(nPeriod/factor); } catch(std::string error) { log->push<Log::ERROR>(error); success=false; break; } varyingWave->push_back(stepper->t()); varyingWave->push_back(stepper->x(),nVar); varyingWave->push_back(stepper->func(),nFunc); } } delete[] x; if(success) log->push<Log::SUCCESS>(identifier); else log->push<Log::FAIL>(identifier); varyingWave->unlock(); }); return task; }
Task* create_guessing_task(std::string identifier, Log* log, EquationSystem* eqsys, Wave* varyingWave, Wave* evWave, double tol) { size_t nVar(eqsys->n_variables()); size_t nFunc(eqsys->n_functions()); auto f_(eqsys->f()); auto dfdx_(eqsys->dfdx()); #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wpadded" Newton::F f = eqsys->dfdx()? Newton::F([f_,dfdx_,nVar](const double* x, double* rhs) { f_(x,rhs); dfdx_(x,rhs+nVar); }): Newton::F(f_); auto ff(eqsys->func()); bool genJac = eqsys->dfdx()?false:true; Task* task = new Task ([nVar,nFunc,f,ff,varyingWave,evWave,tol,genJac,identifier,log]() mutable { varyingWave->lock(); double* x(new double[nVar]); double* funcs(new double[nFunc]); double t(varyingWave->data()[0]); for(size_t i(0);i<nVar;++i) x[i]=varyingWave->data()[i+1]; varyingWave->pop_back(1+nVar+nFunc); bool success(false); try { success=newton(int(nVar),x,f,genJac,tol); } catch(std::string error) { success=false; log->push<Log::ERROR>(error); } if(!success) log->push<Log::ERROR>("Newton iteration did not converge\n"); else { // get eigenvalue and eigenvector info double* rhs(new double[nVar*(nVar+1)]); f(x,rhs); double* jac=rhs+nVar; VecD evals,evecs; VecSZ types; eigen(nVar,jac,evals,evecs,types); evWave->push_back(&evals[0],nVar*2); evWave->push_back(&evecs[0],nVar*nVar); for(size_t i(0);i<types.size();++i) evWave->push_back(double(types[i])); /* for(size_t i(0),size(size_t(evWave->data_max()));i<size;++i) std::cout<<evWave->data()[i]<<std::endl;*/ delete[] rhs; } varyingWave->push_back(t); varyingWave->push_back(x,nVar); if(nFunc) { ff(x,funcs); varyingWave->push_back(funcs,nFunc); } delete[] x; delete[] funcs; if(success) log->push<Log::SUCCESS>(identifier); else log->push<Log::FAIL>(identifier); varyingWave->unlock(); }); #pragma clang diagnostic pop return task; }