# Python module for simulated annealing
[![Build Status](https://travis-ci.org/perrygeo/simanneal.svg?branch=master)](https://travis-ci.org/perrygeo/simanneal)
[![PyPI version](https://badge.fury.io/py/simanneal.svg)](https://badge.fury.io/py/simanneal)
This module performs [simulated annealing optimization](http://en.wikipedia.org/wiki/Simulated_annealing) to find the optimal state of a system. It is inspired by the metallurgic process of annealing whereby metals must be cooled at a regular schedule in order to settle into their lowest energy state.
Simulated annealing is used to find a close-to-optimal solution among an extremely large (but finite) set of potential solutions. It is particularly useful for [combinatorial optimization](http://en.wikipedia.org/wiki/Combinatorial_optimization) problems defined by complex objective functions that rely on external data.
The process involves:
1. Randomly **move** or alter the **state**
2. Assess the **energy** of the new state using an objective function
3. Compare the energy to the previous state and
decide whether to accept the new solution or
reject it based on the current **temperature**.
4. Repeat until you have converged on an acceptable answer
For a move to be accepted, it must meet one of two requirements:
* The move causes a decrease in state energy (i.e. an improvement in the objective function)
* The move increases the state energy (i.e. a slightly worse solution) but is within the bounds of the temperature. The temperature exponetially decreases as the algorithm progresses. In this way, we avoid getting trapped by local minima early in the process but start to hone in on a viable solution by the end.
## Example: Travelling Salesman Problem
The quintessential discrete optimization problem is the [travelling salesman problem](http://en.wikipedia.org/wiki/Travelling_salesman_problem).
> Given a list of locations, what is the shortest possible route
> that hits each location and returns to the starting city?
To put it in terms of our simulated annealing framework:
* The **state** is an ordered list of locations to visit
* The **move** shuffles two cities in the list
* The **energy** of a give state is the distance travelled
## Quickstart
Install it first
```bash
pip install simanneal # from pypi
pip install -e git+https://github.com/perrygeo/simanneal.git # latest from github
```
To define our problem, we create a class that inherits from `simanneal.Annealer`
```python
from simanneal import Annealer
class TravellingSalesmanProblem(Annealer):
"""Test annealer with a travelling salesman problem."""
```
Within that class, we define two required methods. First, we define the move:
```python
def move(self):
"""Swaps two cities in the route."""
a = random.randint(0, len(self.state) - 1)
b = random.randint(0, len(self.state) - 1)
self.state[a], self.state[b] = self.state[b], self.state[a]
```
Then we define how energy is computed (also known as the *objective function*):
```python
def energy(self):
"""Calculates the length of the route."""
e = 0
for i in range(len(self.state)):
e += self.distance(cities[self.state[i - 1]],
cities[self.state[i]])
return e
```
Note that both of these methods have access to `self.state` which tracks the current state of the process.
So with our problem specified, we can construct a ` TravellingSalesmanProblem` instance and provide it a starting state
```python
initial_state = ['New York', 'Los Angeles', 'Boston', 'Houston']
tsp = TravellingSalesmanProblem(initial_state)
```
And run it
```python
itinerary, miles = tsp.anneal()
```
See [examples/salesman.py](https://github.com/perrygeo/simanneal/blob/master/examples/salesman.py) to see the complete implementation.
## Annealing parameters
Getting the annealing algorithm to work effectively and quickly is a matter of tuning parameters. The defaults are:
```python
Tmax = 25000.0 # Max (starting) temperature
Tmin = 2.5 # Min (ending) temperature
steps = 50000 # Number of iterations
updates = 100 # Number of updates (by default an update prints to stdout)
```
These can vary greatly depending on your objective function and solution space.
A good rule of thumb is that your initial temperature `Tmax` should be set to accept roughly 98% of the moves and that the final temperature `Tmin` should be low enough that the solution does not improve much, if at all.
The number of `steps` can influence the results; if there are not enough iterations to adequately explore the search space it can get trapped at a local minimum.
The number of updates doesn't affect the results but can be useful for examining the progress. The default update method (`Annealer.update`) prints a table to stdout and includes the current temperature, state energy, the percentage of moves accepted and improved and elapsed and remaining time. You can override `.update` and provide your own custom reporting mechanism to e.g. graphically plot the progress.
If you want to specify them manually, the are just attributes of the `Annealer` instance.
```python
tsp.Tmax = 12000.0
...
```
However, you can use the `.auto` method which attempts to explore the search space to determine some decent starting values and assess how long each iteration takes. This allows you to specify roughly how long you're willing to wait for results.
```python
auto_schedule = tsp.auto(minutes=1)
# {'tmin': ..., 'tmax': ..., 'steps': ...}
tsp.set_schedule(auto_schedule)
itinerary, miles = tsp.anneal()
```
## Extra data dependencies
You might have noticed that the `energy` function above requires a `cities` dict
that is presumably defined in the enclosing scope. This is not necessarily a good
design pattern. The dependency on additional data can be made explicit by passing
them into the constructor like so
# pass extra data (the distance matrix) into the constructor
def __init__(self, state, distance_matrix):
self.distance_matrix = distance_matrix
super(TravellingSalesmanProblem, self).__init__(state) # important!
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.
For this reason, a non-`None` value returned from `move` will be treated as
a delta and added to the previous energy value to get the energy value for
the current move. If your model allows you to cheaply calculate a change in
energy from the previous state, this approach will save you a call to
`energy`. It is fine for the `move` operation to sometimes return a delta
value and sometimes return `None`, depending on the type of modification it
makes to the state and the complexity of calculting a delta.
## Implementation Details
The simulated annealing algorithm requires that we track states (current, previous, best), which means we need to copy `self.state` frequently.
Copying an object in Python is not always straightforward or performant. The standard library provides a `copy.deepcopy()` method to copy arbitrary python objects but it is very expensive. Certain objects can be copied by more efficient means: lists can be sliced and dictionaries can use their own .copy method, etc.
In order to facilitate flexibility, you can specify the `copy_strategy` attribute
which defines one of:
* `deepcopy`: uses `copy.deepcopy(object)`
* `slice`: uses `object[:]`
* `method`: uses `object.copy()`
If you want to implement your own custom copy mechanism, override the `copy_state` method.
## Notes
1. Thanks to Richard J. Wagner at University of Michigan for writing and contributing the bulk of this code.
2. Some effort has been made to increase performance but this is nowhere near as fast as optimized solutions written
没有合适的资源?快使用搜索试试~ 我知道了~
用于模拟退火优化 的 Python 模块_python_代码_下载
共20个文件
py:8个
md:2个
txt:2个
1.该资源内容由用户上传,如若侵权请联系客服进行举报
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
版权申诉
0 下载量 20 浏览量
2022-06-21
11:13:12
上传
评论
收藏 761KB ZIP 举报
温馨提示
执行模拟退火优化以找到系统的最佳状态。它的灵感来自于退火的冶金过程,其中金属必须定期冷却,以达到其最低能量状态。 模拟退火用于在极大(但有限)的一组潜在解决方案中找到接近最优的解决方案。它对于由依赖外部数据的复杂目标函数定义的组合优化问题特别有用。 该过程包括: 随机移动或改变状态 使用目标函数评估新状态的能量 将能量与之前的状态进行比较,并根据当前温度决定是接受新的解决方案还是拒绝它。 重复直到你收敛到一个可以接受的答案 要使移动被接受,它必须满足以下两个要求之一: 移动导致状态能量减少(即目标函数的改进) 移动增加了状态能量(即稍差的解决方案),但在温度范围内。随着算法的进行,温度呈指数下降。通过这种方式,我们避免了在流程早期陷入局部最小值,但最终开始磨练可行的解决方案。 更多详情、使用方法,请下载后阅读README.md文件
资源推荐
资源详情
资源评论
收起资源包目录
simanneal-master.zip (20个子文件)
simannester
.travis.yml 311B
release.sh 66B
requirements-dev.txt 23B
tests
helper.py 1KB
test_anneal.py 4KB
simanneal
anneal.py 11KB
__init__.py 114B
CHANGES.md 319B
examples
salesman.py 3KB
watershed
data
huc6_4326.shp 1MB
huc6_4326.prj 143B
huc6_4326.dbf 13KB
huc6_4326.shx 468B
watershed_condition.py 5KB
shapefile.py 38KB
setup.py 1KB
.gitignore 75B
MANIFEST.IN 219B
README.md 9KB
LICENSE.txt 814B
共 20 条
- 1
资源评论
快撑死的鱼
- 粉丝: 1w+
- 资源: 9154
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功