8 #include "SimulatedAnnealing.h"
10 #include "Hamiltonian.h"
11 #include "UnitaryMatrix.h"
12 #include "OrbitalTransform.h"
23 ham.reset(
new DOCIHamiltonian(mol));
31 mt = std::mt19937_64(rd());
40 ham.reset(
new DOCIHamiltonian(mol));
48 mt = std::mt19937_64(rd());
62 return energy + ham->getMolecule().get_nucl_rep();
67 this->max_angle = max_angle;
72 this->delta_angle = delta_angle;
77 this->start_temp = start_temp;
82 this->delta_temp = delta_temp;
92 std::uniform_real_distribution<double> dist_accept(0, 1);
98 double chance = std::exp((energy - e_new) / cur_temp);
100 if ( dist_accept(mt) * (1+chance) > chance)
116 energy = ham->CalcEnergy();
126 auto *mol =
static_cast<Sym_Molecule *
> (&ham->getMolecule());
127 assert(mol &&
"Shit, NULL pointer");
133 return ham->CalcEnergy();
141 std::uniform_int_distribution<int> dist(0, ham->getMolecule().get_n_sp()-1);
142 std::uniform_real_distribution<double> dist_angles(0, 1);
144 auto *mol =
static_cast<Sym_Molecule *
> (&ham->getMolecule());
147 unsigned int unaccepted = 0;
149 energy = calc_new_energy();
150 std::cout <<
"Starting energy = " << get_energy() << std::endl;
152 double lowest_energy = energy;
153 cur_temp = start_temp;
158 for(
unsigned int i=0;i<ham_data.getL();i++)
159 for(
unsigned int j=i+1;j<ham_data.getL();j++)
160 if(ham_data.getOrbitalIrrep(i) != ham_data.getOrbitalIrrep(j))
161 sample_pairs(i,j) = sample_pairs(j,i) = -1;
163 auto start = std::chrono::high_resolution_clock::now();
166 for(i=0;i<max_steps;i++)
168 auto orb1 = dist(mt);
169 auto orb2 = dist(mt);
171 if(orb1 != orb2 && ham_data.getOrbitalIrrep(orb1) == ham_data.getOrbitalIrrep(orb2))
173 sample_pairs(orb1, orb2) += 1;
174 sample_pairs(orb2, orb1) += 1;
177 auto cur_angle = max_angle * (dist_angles(mt) - dist_angles(mt));
179 std::cout << i <<
"\tT=" << cur_temp <<
"\tOrb1=" << orb1 <<
"\tOrb2=" << orb2 <<
" Over " << cur_angle << std::endl;
181 orbtrans->get_unitary().jacobi_rotation(ham_data.getOrbitalIrrep(orb1), orb1, orb2, cur_angle);
183 auto new_energy = calc_new_energy();
185 if(new_energy < lowest_energy)
186 lowest_energy = new_energy;
188 std::cout <<
"T=" << cur_temp <<
"\tNew energy = " << new_energy + mol->
get_nucl_rep() <<
"\t Old energy = " << get_energy();
190 if(accept_function(new_energy))
193 std::cout <<
"\t=> Accepted" << std::endl;
198 std::cout <<
"\t=> Unaccepted, " << unaccepted << std::endl;
199 orbtrans->get_unitary().jacobi_rotation(ham_data.getOrbitalIrrep(orb1), orb1, orb2, -1*cur_angle);
202 cur_temp *= delta_temp;
203 max_angle *= delta_angle;
205 if(unaccepted > 1500)
207 std::cout <<
"Too many unaccepted, stopping" << std::endl;
215 auto end = std::chrono::high_resolution_clock::now();
217 std::cout <<
"Bottom was " << lowest_energy + mol->
get_nucl_rep() << std::endl;
218 std::cout <<
"Final energy = " << get_energy() << std::endl;
219 std::cout <<
"Sim anneal runtime: " << std::fixed << std::chrono::duration_cast<std::chrono::duration<double,std::ratio<1>>>(end-start).count() <<
" s" << std::endl;
221 std::stringstream h5_name;
222 if(getenv(
"SAVE_H5_PATH"))
223 h5_name << getenv(
"SAVE_H5_PATH") <<
"/unitary-final-" << i <<
".h5";
225 h5_name <<
"unitary-final-" << i <<
".h5";
226 orbtrans->get_unitary().saveU(h5_name.str());
228 for(
unsigned int i=0;i<ham_data.getL();i++)
229 for(
unsigned int j=i+1;j<ham_data.getL();j++)
230 if(sample_pairs(i,j) >= 0)
231 std::cout << ham_data.getOrbitalIrrep(i) <<
"\t" << i <<
"\t" << j <<
"\t" << sample_pairs(i,j) << std::endl;
double get_energy() const
doci::DOCIHamiltonian & getHam() const
SimulatedAnnealing(doci::Sym_Molecule &)
void Set_delta_angle(double)
void Set_start_temp(double)
simanneal::OrbitalTransform & getOrbitaltf() const
void Set_max_angle(double)
bool accept_function(double)
void Set_delta_temp(double)
double get_nucl_rep() const
CheMPS2::Hamiltonian & getHamObject() const
virtual ~SimulatedAnnealing()