From 44f65cf9b5f25911ceb4b98f0cf269f8c4c4958e Mon Sep 17 00:00:00 2001 From: Jared Deckard Date: Fri, 2 Aug 2019 08:05:59 -0500 Subject: [PATCH] Allow optimizing per-move energy changes --- README.md | 7 +++++++ simanneal/anneal.py | 9 ++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 975d6a0..ed8207d 100644 --- a/README.md +++ b/README.md @@ -135,6 +135,13 @@ them into the constructor like so The last line (calling init on the super class) is critical. +## Optimizations + +For some problems the `energy` function is prohibitively expensive to calculate +after every move. It is often possible to compute the change in energy that a +move causes much more efficiently. A delta value can be returned from `move` to +update the energy value without calling `energy` multiple times. + ## Implementation Details The simulated annealing algorithm requires that we track state (current, previous, best) and thus means we need to copy the `self.state` frequently. diff --git a/simanneal/anneal.py b/simanneal/anneal.py index ebc5286..6e563d0 100644 --- a/simanneal/anneal.py +++ b/simanneal/anneal.py @@ -193,9 +193,12 @@ def anneal(self): while step < self.steps and not self.user_exit: step += 1 T = self.Tmax * math.exp(Tfactor * step / self.steps) - self.move() - E = self.energy() - dE = E - prevEnergy + dE = self.move() + if dE is None: + E = self.energy() + dE = E - prevEnergy + else: + E += dE trials += 1 if dE > 0.0 and math.exp(-dE / T) < random.random(): # Restore previous state