def runtest(X, pot, natoms = 100, iprint=-1): from _lbfgs_py import PrintEvent tol = 1e-5 maxstep = 0.005 Xinit = np.copy(X) e, g = pot.getEnergyGradient(X) print "energy", e lbfgs = LBFGS(X, pot, maxstep = 0.1, nsteps=10000, tol=tol, iprint=iprint, H0=2.) printevent = PrintEvent( "debugout.xyz") lbfgs.attachEvent(printevent) ret = lbfgs.run() print ret print "" print "now do the same with scipy lbfgs" from pele.optimize import lbfgs_scipy as quench ret = quench(Xinit, pot, tol = tol) print ret #print ret[1], ret[2], ret[3] if False: print "now do the same with scipy bfgs" from pele.optimize import bfgs as oldbfgs ret = oldbfgs(Xinit, pot, tol = tol) print ret if False: print "now do the same with gradient + linesearch" import _bfgs gpl = _bfgs.GradientPlusLinesearch(Xinit, pot, maxstep = 0.1) ret = gpl.run(1000, tol = 1e-6) print ret if False: print "calling from wrapper function" from pele.optimize import lbfgs_py ret = lbfgs_py(Xinit, pot, tol = tol) print ret if True: print "" print "now do the same with lbfgs_py" from pele.optimize import lbfgs_py ret = lbfgs_py(Xinit, pot, tol = tol) print ret try: import pele.utils.pymolwrapper as pym pym.start() for n, coords in enumerate(printevent.coordslist): coords=coords.reshape(natoms, 3) pym.draw_spheres(coords, "A", n) except ImportError: print "error loading pymol"
def lbfgs_py(coords, pot, **kwargs): if not hasattr(pot, "getEnergyGradient"): # for compatibility with old quenchers. # assume pot is a getEnergyGradient function pot = _getEnergyGradientWrapper(pot) lbfgs = LBFGS(coords, pot, **kwargs) return lbfgs.run()
def setUp1(self, verbose=False, **kwargs): np.random.seed(0) natoms = 18 self.system = LJCluster(natoms) self.pot = self.system.get_potential() x = self.system.get_random_configuration() ret = lbfgs_py(x, self.pot, tol=10) self.x = ret.coords self.kwargs = kwargs self.verbose = verbose self.M = 4 if self.verbose: iprint = 1 else: iprint = -1 self.myo = MYLBFGS(self.x, self.pot, iprint=iprint, debug=True, M=self.M) self.o = LBFGS(self.x, self.pot, iprint=iprint, debug=True, M=self.M, **self.kwargs)
def test1(self): pot = DiscontinuousHarmonic() x0 = np.array([-10, 1]) opt = LBFGS(x0, pot, debug=True) print('this runnnns') res = opt.run() self.assertFalse(res.success)
def test_event(self): self.called = False def event(coords=None, energy=None, rms=None): self.called = True opt = LBFGS(self.x0, self.pot, events=[event]) opt.one_iteration() self.assertTrue(self.called)
def _lbfgs_py(coords, pot, **kwargs): lbfgs = LBFGS(coords, pot, **kwargs) ret = lbfgs.run() coords = ret.coords e = ret.energy rms = ret.rms funcalls = ret.nfev return coords, e, rms, funcalls, ret
def test(self): minimizer = LBFGS(self.x.copy(), self.pot, fortran=True, debug=True) ret = minimizer.run() m2 = LBFGS(self.x.copy(), self.pot, fortran=False, debug=True) ret2 = m2.run() print "fortran", ret.nfev, ret2.nfev # self.assertEqual(ret.nfev, ret2.nfev) self.assertAlmostEqual(ret.energy, ret2.energy, 5)
def __init__(self, coords, potential, eigenvec, energy=None, gradient=None, **minimizer_kwargs): self.tspot = _TransversePotential(potential, eigenvec) if energy is not None and gradient is not None: transverse_energy, transverse_gradient = self.tspot.projected_energy_gradient(energy, gradient) else: transverse_energy, transverse_gradient = None, None self.walker = LBFGS(coords, self.tspot, energy=transverse_energy, gradient=transverse_gradient, **minimizer_kwargs)
def test(self): minimizer = LBFGS(self.x.copy(), self.pot, armijo=True, debug=True) ret = minimizer.run() self.assertTrue(ret.success) print "\n\n" minimizer = LBFGS(self.x.copy(), self.pot, armijo=False, debug=True) ret_nowolfe = minimizer.run() self.assertTrue(ret_nowolfe.success) print "nfev armijo, noarmijo", ret.nfev, ret_nowolfe.nfev, ret.energy, ret_nowolfe.energy
def test(self): minimizer = LBFGS(self.x.copy(), self.pot, debug=True) minimizer._use_wolfe = True ret = minimizer.run() self.assertTrue(ret.success) print "\n\n" minimizer = LBFGS(self.x.copy(), self.pot, debug=True) ret_nowolfe = minimizer.run() self.assertTrue(ret_nowolfe.success) print "nfev wolfe, nowolfe", ret.nfev, ret_nowolfe.nfev, ret.energy, ret_nowolfe.energy
def run(X_train): # fit a Gaussian Mixture Model with two components clf = mixture.GMM(n_components=2, covariance_type='full') pot = GMMPotential(clf, X_train) params = pot.get_random_coords() print params e, g = pot.getEnergyGradient(params) print "energy", e print "grad", g opt = LBFGS(params, pot, tol=1e-5, maxstep=1., iprint=1)#, events=[print_event]) res = opt.run() print "finished" e, g = pot.getEnergyGradient(res.coords) print "energy", e print "grad" print "grad", g # raise Exception("exiting early") # clf.fit(X_train) print "weights" print clf.covars_ print "\nmeans" print clf.means_ print "\ncovariances" print clf.covars_ # display predicted scores by the model as a contour plot x = np.linspace(-20.0, 30.0) y = np.linspace(-20.0, 40.0) X, Y = np.meshgrid(x, y) XX = np.array([X.ravel(), Y.ravel()]).T Z = -clf.score_samples(XX)[0] Z = Z.reshape(X.shape) CS = plt.contour(X, Y, Z, norm=LogNorm(vmin=1.0, vmax=1000.0), levels=np.logspace(0, 3, 10)) CB = plt.colorbar(CS, shrink=0.8, extend='both') plt.scatter(X_train[:, 0], X_train[:, 1], .8) plt.title('Negative log-likelihood predicted by a GMM') plt.axis('tight') make_ellipses(clf, plt.gca()) plt.show()
def __init__(self, coords, potential, eigenvec, quenchRoutine=None, **minimizer_kwargs): self.dimer_potential = _DimerPotential(potential, eigenvec) if quenchRoutine: self.minimizer = quenchRoutine(coords, self.dimer_potential, **minimizer_kwargs) else: self.minimizer = LBFGS(coords, self.dimer_potential, **minimizer_kwargs)
def test(self): minimizer = LBFGS(self.x.copy(), self.pot, debug=True) minimizer._cython = True ret = minimizer.run() m2 = LBFGS(self.x.copy(), self.pot, debug=True) minimizer._cython = True ret2 = m2.run() print("cython", ret.nfev, ret2.nfev) self.assertEqual(ret.nfev, ret2.nfev) self.assertAlmostEqual(ret.energy, ret2.energy, 5)
def test(self): minimizer = LBFGS(self.x.copy(), self.pot, fortran=True, debug=True) ret = minimizer.run() m2 = LBFGS(self.x.copy(), self.pot, fortran=False, debug=True) ret2 = m2.run() print("fortran", ret.nfev, ret2.nfev) # self.assertEqual(ret.nfev, ret2.nfev) self.assertAlmostEqual(ret.energy, ret2.energy, 5)
def test(self): minimizer = LBFGS(self.x.copy(), self.pot, debug=True) minimizer._cython = True ret = minimizer.run() m2 = LBFGS(self.x.copy(), self.pot, debug=True) minimizer._cython = True ret2 = m2.run() print "cython", ret.nfev, ret2.nfev self.assertEqual(ret.nfev, ret2.nfev) self.assertAlmostEqual(ret.energy, ret2.energy, 5)
def setUp1(self, verbose=False, **kwargs): np.random.seed(0) natoms = 18 self.system = LJCluster(natoms) self.pot = self.system.get_potential() x = self.system.get_random_configuration() ret = lbfgs_py(x, self.pot, tol=10) self.x = ret.coords self.kwargs = kwargs self.verbose = verbose self.M = 4 if self.verbose: iprint=1 else: iprint = -1 self.myo = MYLBFGS(self.x, self.pot, iprint=iprint, debug=True, M=self.M) self.o = LBFGS(self.x, self.pot, iprint=iprint, debug=True, M=self.M, **self.kwargs)
class TestLBFGS_State(unittest.TestCase): def setUp(self): self.system = LJCluster(13) self.x = self.system.get_random_configuration() self.pot = self.system.get_potential() self.minimizer = LBFGS(self.x, self.pot) def test_state(self): # do several minimization iterations for i in xrange(10): self.minimizer.one_iteration() # get the state and save it ret = self.minimizer.get_result() state = self.minimizer.get_state() x1 = ret.coords.copy() # do several more iteration steps for i in xrange(10): self.minimizer.one_iteration() # now make a new minimizer and do several iterations minimizer2 = LBFGS(x1, self.pot) minimizer2.set_state(state) for i in xrange(10): minimizer2.one_iteration() # test that the two minimizers are in the same state ret1 = self.minimizer.get_result() ret2 = minimizer2.get_result() self.assertEqual(ret1.energy, ret2.energy) self.assertTrue((ret1.coords == ret2.coords).all()) state1 = self.minimizer.get_state() state2 = minimizer2.get_state() self.assertTrue((state1.y == state2.y).all()) self.assertTrue((state1.s == state2.s).all()) self.assertTrue((state1.rho == state2.rho).all()) self.assertTrue((state1.dXold == state2.dXold).all()) self.assertTrue((state1.dGold == state2.dGold).all()) self.assertEqual(state1.H0, state2.H0) self.assertEqual(state1.k, state2.k)
def test(self): minimizer = LBFGS(self.x.copy(), self.pot, armijo=True, debug=True) ret = minimizer.run() self.assertTrue(ret.success) print "\n\n" minimizer = LBFGS(self.x.copy(), self.pot, armijo=False, debug=True) ret_nowolfe = minimizer.run() self.assertTrue(ret_nowolfe.success) self.assertAlmostEqual(ret.energy, ret_nowolfe.energy, delta=1e-3) print "nfev armijo, noarmijo", ret.nfev, ret_nowolfe.nfev, ret.energy, ret_nowolfe.energy
def test_state(self): # do several minimization iterations for i in range(10): self.minimizer.one_iteration() # get the state and save it ret = self.minimizer.get_result() state = self.minimizer.get_state() x1 = ret.coords.copy() # do several more iteration steps for i in range(10): self.minimizer.one_iteration() # now make a new minimizer and do several iterations minimizer2 = LBFGS(x1, self.pot) minimizer2.set_state(state) for i in range(10): minimizer2.one_iteration() # test that the two minimizers are in the same state ret1 = self.minimizer.get_result() ret2 = minimizer2.get_result() self.assertEqual(ret1.energy, ret2.energy) self.assertTrue((ret1.coords == ret2.coords).all()) state1 = self.minimizer.get_state() state2 = minimizer2.get_state() self.assertTrue((state1.y == state2.y).all()) self.assertTrue((state1.s == state2.s).all()) self.assertTrue((state1.rho == state2.rho).all()) self.assertTrue((state1.dXold == state2.dXold).all()) self.assertTrue((state1.dGold == state2.dGold).all()) self.assertEqual(state1.H0, state2.H0) self.assertEqual(state1.k, state2.k)
def test_state(self): # do several minimization iterations for i in xrange(10): self.minimizer.one_iteration() # get the state and save it ret = self.minimizer.get_result() state = self.minimizer.get_state() x1 = ret.coords.copy() # do several more iteration steps for i in xrange(10): self.minimizer.one_iteration() # now make a new minimizer and do several iterations minimizer2 = LBFGS(x1, self.pot) minimizer2.set_state(state) for i in xrange(10): minimizer2.one_iteration() # test that the two minimizers are in the same state ret1 = self.minimizer.get_result() ret2 = minimizer2.get_result() self.assertEqual(ret1.energy, ret2.energy) self.assertTrue((ret1.coords == ret2.coords).all()) state1 = self.minimizer.get_state() state2 = minimizer2.get_state() self.assertTrue((state1.y == state2.y).all()) self.assertTrue((state1.s == state2.s).all()) self.assertTrue((state1.rho == state2.rho).all()) self.assertTrue((state1.dXold == state2.dXold).all()) self.assertTrue((state1.dGold == state2.dGold).all()) self.assertEqual(state1.H0, state2.H0) self.assertEqual(state1.k, state2.k)
class _TransverseWalker(object): """It minimizes the energy in the direction perpendicular to a vector this class manages the minimization _TransversePotential Parameters ---------- coords : float array the starting coordinates potential : Potential object eigenvec : float array energy will be minimized in the direction perpendicular to this vector energy, gradient : float and float array the energy and gradient at position coords minimizer_kwargs : kwargs these kwargs are passed to the minimizer """ def __init__(self, coords, potential, eigenvec, energy=None, gradient=None, **minimizer_kwargs): self.tspot = _TransversePotential(potential, eigenvec) if energy is not None and gradient is not None: transverse_energy, transverse_gradient = self.tspot.projected_energy_gradient(energy, gradient) else: transverse_energy, transverse_gradient = None, None self.walker = LBFGS(coords, self.tspot, energy=transverse_energy, gradient=transverse_gradient, **minimizer_kwargs) def update_eigenvec(self, eigenvec, eigenval): """update the vecotr""" self.tspot.update_vector(eigenvec) def update_maxstep(self, maxstep): """update the maximum step size of the minimizer""" self.walker.maxstep = float(maxstep) def update_coords(self, coords, true_energy, true_gradient): """update the position of the optimizer this must be called after update_eigenvec """ energy, gradient = self.tspot.projected_energy_gradient(true_energy, true_gradient) self.walker.update_coords(coords, energy, gradient) def stop_criterion_satisfied(self): """test if the stop criterion is satisfied""" return self.walker.stop_criterion_satisfied() def get_true_energy_gradient(self, coords): """return the true energy and gradient""" return self.tspot.get_true_energy_gradient(coords) # def get_energy(self): # """return the true energy # # warning it's possible for this to return the wrong energy if the minimizer # had an aborted line search on the last iteration. # """ # return self.tspot.true_energy # # def get_gradient(self): # """return the true gradient # # warning it's possible for this to return the wrong energy if the minimizer # had an aborted line search on the last iteration. # """ # return self.tspot.true_gradient def get_result(self): """return the results object""" ret = self.walker.get_result() ret.nfev = self.tspot.nfev return ret def run(self, niter): """do a specified number of iterations, or until the stop criterion is satisfied""" for i in range(niter): if self.stop_criterion_satisfied(): break self.walker.one_iteration() return self.get_result()
class TestLBFGS_State(unittest.TestCase): def setUp(self): self.system = LJCluster(13) self.x = self.system.get_random_configuration() self.pot = self.system.get_potential() self.minimizer = LBFGS(self.x, self.pot) def test_state(self): # do several minimization iterations for i in xrange(10): self.minimizer.one_iteration() # get the state and save it ret = self.minimizer.get_result() state = self.minimizer.get_state() x1 = ret.coords.copy() # do several more iteration steps for i in xrange(10): self.minimizer.one_iteration() # now make a new minimizer and do several iterations minimizer2 = LBFGS(x1, self.pot) minimizer2.set_state(state) for i in xrange(10): minimizer2.one_iteration() # test that the two minimizers are in the same state ret1 = self.minimizer.get_result() ret2 = minimizer2.get_result() self.assertEqual(ret1.energy, ret2.energy) self.assertTrue((ret1.coords == ret2.coords).all()) state1 = self.minimizer.get_state() state2 = minimizer2.get_state() self.assertTrue((state1.y == state2.y).all()) self.assertTrue((state1.s == state2.s).all()) self.assertTrue((state1.rho == state2.rho).all()) self.assertTrue((state1.dXold == state2.dXold).all()) self.assertTrue((state1.dGold == state2.dGold).all()) self.assertEqual(state1.H0, state2.H0) self.assertEqual(state1.k, state2.k) def test_reset(self): # do several minimization iterations m1 = LBFGS(self.x, self.pot) for i in xrange(10): m1.one_iteration() # reset the minimizer and do it again m1.reset() e, g = self.pot.getEnergyGradient(self.x) m1.update_coords(self.x, e, g) for i in xrange(10): m1.one_iteration() # do the same number of steps of a new minimizer m2 = LBFGS(self.x, self.pot) for i in xrange(10): m2.one_iteration() # they should be the same (more or less) n = min(m1.k, m1.M) self.assertAlmostEqual(m1.H0, m2.H0, 5) self.assertEqual(m1.k, m2.k) arrays_nearly_equal(self, m1.y[:n, :], m2.y[:n, :]) arrays_nearly_equal(self, m1.s[:n, :], m2.s[:n, :]) arrays_nearly_equal(self, m1.rho[:n], m2.rho[:n]) res1 = m1.get_result() res2 = m2.get_result() self.assertNotEqual(res1.nfev, res2.nfev) self.assertNotEqual(res1.nsteps, res2.nsteps) self.assertAlmostEqual(res1.energy, res2.energy) arrays_nearly_equal(self, res1.coords, res2.coords)
def reset(self): LBFGS.reset(self) self._iter = 0
def lbfgs_py(coords, pot, **kwargs): lbfgs = LBFGS(coords, pot, **kwargs) return lbfgs.run()
def test1(self): pot = DiscontinuousHarmonic() x0 = np.array([-10, 1]) opt = LBFGS(x0, pot, debug=True) res = opt.run() self.assertFalse(res.success)
class TestMYLBFGS_LBFGS(unittest.TestCase): def setUp(self): self.setUp1(verbose=False) def setUp1(self, verbose=False, **kwargs): np.random.seed(0) natoms = 18 self.system = LJCluster(natoms) self.pot = self.system.get_potential() x = self.system.get_random_configuration() ret = lbfgs_py(x, self.pot, tol=10) self.x = ret.coords self.kwargs = kwargs self.verbose = verbose self.M = 4 if self.verbose: iprint=1 else: iprint = -1 self.myo = MYLBFGS(self.x, self.pot, iprint=iprint, debug=True, M=self.M) self.o = LBFGS(self.x, self.pot, iprint=iprint, debug=True, M=self.M, **self.kwargs) def test(self): N = self.x.size M = self.M myo = self.myo o = self.o # do one iteration for i in xrange(3 * self.M): myo.one_iteration() o.one_iteration() if self.verbose: print "" print "H0", myo.H0, o.H0 print "rho ", o.rho[:] print "myrho", myo.W[N:N+M] myret = myo.get_result() ret = o.get_result() self.assertAlmostEqual(ret.energy, myret.energy, 4) self.assertLess(np.max(np.abs(myret.coords - ret.coords)), 1e-6) # do a second iteration for i in xrange(1): myo.one_iteration() o.one_iteration() myret = myo.get_result() ret = o.get_result() if self.verbose: print "H0", myret.H0, ret.H0 print "rho ", o.rho[:] print "myrho", myo.W[N:N+M] self.assertAlmostEqual(ret.energy, myret.energy, 4) self.assertLess(np.max(np.abs(myret.coords - ret.coords)), 1e-6) def test_complete(self): myret = self.myo.run() ret = self.o.run() self.assertEqual(ret.nfev, myret.nfev) self.assertEqual(ret.nsteps, myret.nsteps) self.assertAlmostEqual(ret.energy, myret.energy, 4) self.assertLess(np.max(np.abs(myret.coords - ret.coords)), 1e-6)
def __init__(self, coords, potential, eigenvec, **minimizer_kwargs): self.dimer_potential = _DimerPotential(potential, eigenvec) self.minimizer = LBFGS(coords, self.dimer_potential, **minimizer_kwargs)
class _DimerTranslator(object): """object to manage the translation of the dimer using an optimization algorithm Parameters ---------- coords : float array the starting point of the dimer potential : Potential object eigenvec : float array the initial direction along which the dimer lies minimizer_kwargs : kwargs these kwargs are passed to the optimizer """ def __init__(self, coords, potential, eigenvec, **minimizer_kwargs): self.dimer_potential = _DimerPotential(potential, eigenvec) self.minimizer = LBFGS(coords, self.dimer_potential, **minimizer_kwargs) def stop_criterion_satisfied(self): """test if the stop criterion is satisfied""" return self.minimizer.stop_criterion_satisfied() def get_true_energy_gradient(self, coords): """return the true energy and gradient""" return self.dimer_potential.get_true_energy_gradient(coords) # def get_energy(self): # """return the true energy""" # return self.dimer_potential.true_energy # # def get_gradient(self): # """return the true gradient""" # return self.dimer_potential.true_gradient def update_eigenvec(self, eigenvec, eigenval): """update the direction (rotation) of the dimer""" self.dimer_potential.update_eigenvec(eigenvec) def update_coords(self, coords, true_energy, true_gradient): """update the position of the dimer this must be called after update_eigenvec """ energy, gradient = self.dimer_potential.projected_energy_gradient(true_energy, true_gradient) self.minimizer.update_coords(coords, energy, gradient) def update_maxstep(self, maxstep): """change the maximum step size of the optimizer""" self.minimizer.maxstep = float(maxstep) def run(self, niter): """do a specified number of iterations, or until the stop criterion is satisfied""" for i in xrange(niter): if self.stop_criterion_satisfied(): break self.minimizer.one_iteration() return self.get_result() def get_result(self): """return the results object""" return self.minimizer.get_result() def projected_energy_gradient(self, energy, gradient): """return the projected energy and gradient""" return self.dimer_potential.projected_energy_gradient(energy, gradient)
def test_reset(self): # do several minimization iterations m1 = LBFGS(self.x, self.pot) for i in xrange(10): m1.one_iteration() # reset the minimizer and do it again m1.reset() e, g = self.pot.getEnergyGradient(self.x) m1.update_coords(self.x, e, g) for i in xrange(10): m1.one_iteration() # do the same number of steps of a new minimizer m2 = LBFGS(self.x, self.pot) for i in xrange(10): m2.one_iteration() # they should be the same (more or less) n = min(m1.k, m1.M) self.assertAlmostEqual(m1.H0, m2.H0, 5) self.assertEqual(m1.k, m2.k) arrays_nearly_equal(self, m1.y[:n, :], m2.y[:n, :]) arrays_nearly_equal(self, m1.s[:n, :], m2.s[:n, :]) arrays_nearly_equal(self, m1.rho[:n], m2.rho[:n]) res1 = m1.get_result() res2 = m2.get_result() self.assertNotEqual(res1.nfev, res2.nfev) self.assertNotEqual(res1.nsteps, res2.nsteps) self.assertAlmostEqual(res1.energy, res2.energy) arrays_nearly_equal(self, res1.coords, res2.coords)
class TestLBFGS_State(unittest.TestCase): def setUp(self): self.system = LJCluster(13) self.x = self.system.get_random_configuration() self.pot = self.system.get_potential() self.minimizer = LBFGS(self.x, self.pot) def test_state(self): # do several minimization iterations for i in range(10): self.minimizer.one_iteration() # get the state and save it ret = self.minimizer.get_result() state = self.minimizer.get_state() x1 = ret.coords.copy() # do several more iteration steps for i in range(10): self.minimizer.one_iteration() # now make a new minimizer and do several iterations minimizer2 = LBFGS(x1, self.pot) minimizer2.set_state(state) for i in range(10): minimizer2.one_iteration() # test that the two minimizers are in the same state ret1 = self.minimizer.get_result() ret2 = minimizer2.get_result() self.assertEqual(ret1.energy, ret2.energy) self.assertTrue((ret1.coords == ret2.coords).all()) state1 = self.minimizer.get_state() state2 = minimizer2.get_state() self.assertTrue((state1.y == state2.y).all()) self.assertTrue((state1.s == state2.s).all()) self.assertTrue((state1.rho == state2.rho).all()) self.assertTrue((state1.dXold == state2.dXold).all()) self.assertTrue((state1.dGold == state2.dGold).all()) self.assertEqual(state1.H0, state2.H0) self.assertEqual(state1.k, state2.k) def test_reset(self): # do several minimization iterations m1 = LBFGS(self.x, self.pot) for i in range(10): m1.one_iteration() # reset the minimizer and do it again m1.reset() e, g = self.pot.getEnergyGradient(self.x) m1.update_coords(self.x, e, g) for i in range(10): m1.one_iteration() # do the same number of steps of a new minimizer m2 = LBFGS(self.x, self.pot) for i in range(10): m2.one_iteration() # they should be the same (more or less) n = min(m1.k, m1.M) self.assertAlmostEqual(m1.H0, m2.H0, 5) self.assertEqual(m1.k, m2.k) arrays_nearly_equal(self, m1.y[:n, :], m2.y[:n, :]) arrays_nearly_equal(self, m1.s[:n, :], m2.s[:n, :]) arrays_nearly_equal(self, m1.rho[:n], m2.rho[:n]) res1 = m1.get_result() res2 = m2.get_result() self.assertNotEqual(res1.nfev, res2.nfev) self.assertNotEqual(res1.nsteps, res2.nsteps) self.assertAlmostEqual(res1.energy, res2.energy) arrays_nearly_equal(self, res1.coords, res2.coords)
def setUp(self): self.system = LJCluster(13) self.x = self.system.get_random_configuration() self.pot = self.system.get_potential() self.minimizer = LBFGS(self.x, self.pot)
class _TransverseWalker(object): """It minimizes the energy in the direction perpendicular to a vector this class manages the minimization _TransversePotential Parameters ---------- coords : float array the starting coordinates potential : Potential object eigenvec : float array energy will be minimized in the direction perpendicular to this vector energy, gradient : float and float array the energy and gradient at position coords minimizer_kwargs : kwargs these kwargs are passed to the minimizer """ def __init__(self, coords, potential, eigenvec, energy=None, gradient=None, **minimizer_kwargs): self.tspot = _TransversePotential(potential, eigenvec) if energy is not None and gradient is not None: transverse_energy, transverse_gradient = self.tspot.projected_energy_gradient( energy, gradient) else: transverse_energy, transverse_gradient = None, None self.walker = LBFGS(coords, self.tspot, energy=transverse_energy, gradient=transverse_gradient, **minimizer_kwargs) def update_eigenvec(self, eigenvec, eigenval): """update the vecotr""" self.tspot.update_vector(eigenvec) def update_maxstep(self, maxstep): """update the maximum step size of the minimizer""" self.walker.maxstep = float(maxstep) def update_coords(self, coords, true_energy, true_gradient): """update the position of the optimizer this must be called after update_eigenvec """ energy, gradient = self.tspot.projected_energy_gradient( true_energy, true_gradient) self.walker.update_coords(coords, energy, gradient) def stop_criterion_satisfied(self): """test if the stop criterion is satisfied""" return self.walker.stop_criterion_satisfied() def get_true_energy_gradient(self, coords): """return the true energy and gradient""" return self.tspot.get_true_energy_gradient(coords) # def get_energy(self): # """return the true energy # # warning it's possible for this to return the wrong energy if the minimizer # had an aborted line search on the last iteration. # """ # return self.tspot.true_energy # # def get_gradient(self): # """return the true gradient # # warning it's possible for this to return the wrong energy if the minimizer # had an aborted line search on the last iteration. # """ # return self.tspot.true_gradient def get_result(self): """return the results object""" ret = self.walker.get_result() ret.nfev = self.tspot.nfev return ret def run(self, niter): """do a specified number of iterations, or until the stop criterion is satisfied""" for i in range(niter): if self.stop_criterion_satisfied(): break self.walker.one_iteration() return self.get_result()
def test_reset(self): # do several minimization iterations m1 = LBFGS(self.x, self.pot) for i in range(10): m1.one_iteration() # reset the minimizer and do it again m1.reset() e, g = self.pot.getEnergyGradient(self.x) m1.update_coords(self.x, e, g) for i in range(10): m1.one_iteration() # do the same number of steps of a new minimizer m2 = LBFGS(self.x, self.pot) for i in range(10): m2.one_iteration() # they should be the same (more or less) n = min(m1.k, m1.M) self.assertAlmostEqual(m1.H0, m2.H0, 5) self.assertEqual(m1.k, m2.k) arrays_nearly_equal(self, m1.y[:n, :], m2.y[:n, :]) arrays_nearly_equal(self, m1.s[:n, :], m2.s[:n, :]) arrays_nearly_equal(self, m1.rho[:n], m2.rho[:n]) res1 = m1.get_result() res2 = m2.get_result() self.assertNotEqual(res1.nfev, res2.nfev) self.assertNotEqual(res1.nsteps, res2.nsteps) self.assertAlmostEqual(res1.energy, res2.energy) arrays_nearly_equal(self, res1.coords, res2.coords)
class _DimerTranslator(object): """object to manage the translation of the dimer using an optimization algorithm Parameters ---------- coords : float array the starting point of the dimer potential : Potential object eigenvec : float array the initial direction along which the dimer lies minimizer_kwargs : kwargs these kwargs are passed to the optimizer """ def __init__(self, coords, potential, eigenvec, **minimizer_kwargs): self.dimer_potential = _DimerPotential(potential, eigenvec) self.minimizer = LBFGS(coords, self.dimer_potential, **minimizer_kwargs) def stop_criterion_satisfied(self): """test if the stop criterion is satisfied""" return self.minimizer.stop_criterion_satisfied() def get_true_energy_gradient(self, coords): """return the true energy and gradient""" return self.dimer_potential.get_true_energy_gradient(coords) # def get_energy(self): # """return the true energy""" # return self.dimer_potential.true_energy # # def get_gradient(self): # """return the true gradient""" # return self.dimer_potential.true_gradient def update_eigenvec(self, eigenvec, eigenval): """update the direction (rotation) of the dimer""" self.dimer_potential.update_eigenvec(eigenvec) def update_coords(self, coords, true_energy, true_gradient): """update the position of the dimer this must be called after update_eigenvec """ energy, gradient = self.dimer_potential.projected_energy_gradient( true_energy, true_gradient) self.minimizer.update_coords(coords, energy, gradient) def update_maxstep(self, maxstep): """change the maximum step size of the optimizer""" self.minimizer.maxstep = float(maxstep) def run(self, niter): """do a specified number of iterations, or until the stop criterion is satisfied""" for i in xrange(niter): if self.stop_criterion_satisfied(): break self.minimizer.one_iteration() return self.get_result() def get_result(self): """return the results object""" return self.minimizer.get_result() def projected_energy_gradient(self, energy, gradient): """return the projected energy and gradient""" return self.dimer_potential.projected_energy_gradient(energy, gradient)
class TestMYLBFGS_LBFGS(unittest.TestCase): def setUp(self): self.setUp1(verbose=False) def setUp1(self, verbose=False, **kwargs): np.random.seed(0) natoms = 18 self.system = LJCluster(natoms) self.pot = self.system.get_potential() x = self.system.get_random_configuration() ret = lbfgs_py(x, self.pot, tol=10) self.x = ret.coords self.kwargs = kwargs self.verbose = verbose self.M = 4 if self.verbose: iprint = 1 else: iprint = -1 self.myo = MYLBFGS(self.x, self.pot, iprint=iprint, debug=True, M=self.M) self.o = LBFGS(self.x, self.pot, iprint=iprint, debug=True, M=self.M, **self.kwargs) def test(self): N = self.x.size M = self.M myo = self.myo o = self.o # do one iteration for i in range(3 * self.M): myo.one_iteration() o.one_iteration() if self.verbose: print("") print("H0", myo.H0, o.H0) print("rho ", o.rho[:]) print("myrho", myo.W[N:N + M]) myret = myo.get_result() ret = o.get_result() self.assertAlmostEqual(ret.energy, myret.energy, 4) self.assertLess(np.max(np.abs(myret.coords - ret.coords)), 1e-6) # do a second iteration for i in range(1): myo.one_iteration() o.one_iteration() myret = myo.get_result() ret = o.get_result() if self.verbose: print("H0", myret.H0, ret.H0) print("rho ", o.rho[:]) print("myrho", myo.W[N:N + M]) self.assertAlmostEqual(ret.energy, myret.energy, 4) self.assertLess(np.max(np.abs(myret.coords - ret.coords)), 1e-6) def test_complete(self): myret = self.myo.run() ret = self.o.run() self.assertEqual(ret.nfev, myret.nfev) self.assertEqual(ret.nsteps, myret.nsteps) self.assertAlmostEqual(ret.energy, myret.energy, 4) self.assertLess(np.max(np.abs(myret.coords - ret.coords)), 1e-6)