美文网首页
算法_Simulated-Annealing_Python

算法_Simulated-Annealing_Python

作者: 计算士 | 来源:发表于2015-05-30 05:22 被阅读755次

本文用到的包

import random
import numpy as np
from numpy import linalg as LA
import pylab as plt
import networkx as nx
import sys

Simulated-Annealing (模拟退火) 是一种常见的优化方法。这里我们用它将一个任意维度的网络嵌入二维空间。为了检验算法效果,我们先制造一个二维网络A,从这个网络上我们可以得到任意两点之间的欧式距离。我们重新生成一个同等规模的随机网络C,利用C网络两点之间距离与A网络对应距离的差异,来促使C不断朝A演化,经过一千步得到B。可以看出效果非常好,几乎完全恢复了已有网络的结构。

图1. 使用SA方法恢复网络结构图1. 使用SA方法恢复网络结构

SA的思路来源于统计力学中的波尔兹曼分布。该分布假设,一个多粒子系统的态出现的概率与其总能量反比,同时这种反比关系受到温度约束。

![Eq. 1][1]
[1]: http://latex.codecogs.com/svg.latex?P({state})\propto{e^{-\frac{E}{kT}}}

上式中E代表系统能量,k是一个非常小的常数,T是系统的温度。我们在其他系统中,如果将要最小化的某个目标(往往是sum of squares)看做能量,则玻尔兹曼分布给我们建议了一种梯度下降的具体方法,因为从公式1我们可以推得

![Eq. 2][2]
[2]: http://latex.codecogs.com/svg.latex?\frac{P({state2})}{P({state1})}=e^{\frac{E_1-E_2}{kT}}

于是,在实际优化过程中,我们先可以对系统做一小调整,在本例中就是比照目标网络对初始网络中的节点位置进行微调,计算这个调整带来的“能量”差异,然后通过Eq.2来判断这个调整是否应该被接受。

与死板地接受所有带来能量下降的调整的优化方法不同,模拟退火可以保证系统有一定的自由度:以小概率接受短期看不利,但长期可能有利的变化,使得系统不会被锁死在一个变化轨道上。所谓模拟退火,模拟指的就是早期保持较高的稳定,给系统较大的自由度接受短期不利的变化;后期降低温度,使得系统稳定地朝一个方向演化。

将上述思想转化为Python函数如下:

# -----------simulated annealing functions----------------------

# refreshing results
def flushPrint(variable):
    sys.stdout.write('\r')
    sys.stdout.write('%s' % variable)
    sys.stdout.flush()
    
# calculate variance contributed by a node or all nodes 
def varaince(newPos,Dis,node,nodePosition):
    if len(nodePosition) == 2:
        return sum([(LA.norm(newPos[j]-nodePosition)-Dis[(min(node,j),max(node,j))])**2 for j in newPos if j!=node])
    else:
        return 2*sum([(LA.norm(newPos[j]-newPos[i])-Dis[(i,j)])**2 for i,j in Dis])  
    
def moveOneNode(newPos,Dis):
    k = 1.0/len(newPos) #factor to normalize force
    [i] = random.sample(newPos,1)
    newpos_i = np.array(list(newPos[i]))# prevent Python from connecting the value of newPos[i] with newpos_i
    varianceBefore = varaince(newPos,Dis,i,newpos_i)
    for j in newPos:
        newDis = LA.norm(newPos[j]-newpos_i)
        if j!=i and newDis!=0:
            oldDis = Dis[(min(i,j),max(i,j))]
            deltaDis = newDis - oldDis # magnitude and direction of the force j imposing on i
            newpos_i += (newPos[j]-newPos[i])*k*deltaDis/newDis # j pushes/pulls i
    varianceAfter = varaince(newPos,Dis,i,newpos_i)
    deltaE = varianceAfter-varianceBefore
    return i,newpos_i,deltaE

def SA(newPos,Dis,Nsimulate,BoltzmanConstant,Temperature,coolingSpeed):
    v=varaince(newPos,Dis,"null","null")
    V=[v]
    for k in range(Nsimulate):
        flushPrint(k)
        i,newpos_i,deltaE = moveOneNode(newPos,Dis)
        if np.random.rand()<np.exp(-deltaE/(Temperature*BoltzmanConstant)):
            newPos[i] = newpos_i
            Temperature *= coolingSpeed 
            v += deltaE
            V.append(v)
    return newPos,V

现在制造两个网络,一个用于作为优化目标,另一个作为初始状态

# -----------initialization----------------
# generating a random network in 2D space #
N = 20
Pos = dict((i,np.random.rand(2)) for i in range(N))
Dis = {}
E = nx.Graph()
for i in Pos:
    for j in Pos:
        if i<j:
            dis = LA.norm(Pos[j]-Pos[i])
            Dis[(i,j)] = dis
            if dis < 0.4:
                E.add_edge(i,j,weight=dis)
                
# generate new 2d nodes
L = max(Dis.values()) #character length of the universe
newPos = dict((i,np.random.rand(2)*L) for i in range(N))
newPosCopy = newPos.copy() # copy it for plotting initial state

本例中因为系统规模较小,可以设定参数进行如下演化

newPos,V=SA(newPos,Dis,Nsimulate=1000, BoltzmanConstant=.01, Temperature=1, coolingSpeed = .9)

先定义绘制网络的函数

def plotG(ax,positions,edges):
    #nx,ny = zip(*nodes.values())
    for i in positions:
        xi,yi = positions[i]
        ax.scatter(xi,yi,s=300,facecolor='RoyalBlue',edgecolor='gray')
        ax.text(xi,yi,i,ha='center',va='center',size=10,color='white')
    for i,j in edges:
        x1,y1 = positions[i]
        x2,y2 = positions[j]
        ax.plot([x1,x2],[y1,y2],marker='',linestyle='-',color='gray',alpha=0.3)

最后通过以下代码得到图1

fig = plt.figure(figsize=(10, 10))
ax1 = fig.add_subplot(221)
plotG(ax1,Pos,E.edges())
plt.text(.9,.9,'A',size=14)
ax2 = fig.add_subplot(222)
plt.text(.9,1.1,'B',size=14)
plotG(ax2,newPos,E.edges())
ax3 = fig.add_subplot(223)
plt.text(.9,.9,'C',size=14)
plotG(ax3,newPosCopy,E.edges())
ax3 = fig.add_subplot(224)
plt.text(900,37,'D',size=14)
plt.plot(V,marker='.',linestyle='-',color='RoyalBlue')
plt.xlabel('Simulation steps')
plt.ylabel('Variance')
#
plt.tight_layout()
plt.show()
#plt.savefig('/Users/csid/Desktop/SA.png',transparent=True)

相关文章

  • 算法_Simulated-Annealing_Python

    本文用到的包 Simulated-Annealing (模拟退火) 是一种常见的优化方法。这里我们用它将一个任意维...

  • 匈牙利算法

    算法思想 算法流程 算法步骤 算法实现 python 算法应用

  • web开发需要知道的几个算法

    算法分类 快速排序算法 深度优先算法 广度优先算法 堆排序算法 归并排序算法

  • 机器学习算法

    机器学习的算法分监督算法和无监督 算法。监督算法包括回归算法,神经网络,SVM;无监督算法包括聚类算法,降维算法。...

  • 字符串匹配

    BF 算法和 RK 算法BM 算法和 KMP 算法

  • 垃圾回收算法有几种类型? 他们对应的优缺点又是什么?

    常见的垃圾回收算法有: 标记-清除算法、复制算法、标记-整理算法、分代收集算法 标记-清除算法 标记—清除算法包括...

  • 头条-手撕代码

    [toc] 图算法 以及最短路径算法 树算法 手写LRU 排序算法 链表算法

  • 关于一些算法

    我们平常说的算法按照使用方向加密算法,排序算法,搜索算法,优化算法,音视频处理算法,图片处理算法 1.加密解密算法...

  • 给我巨大影响的技术书籍

    算法《算法概论》《算法设计与分析基础》 Anany Levitin《算法引论》Udi Manber《算法导论》《什...

  • 缓存相关

    cache淘汰算法:LIRS 算法 缓存那些事 Redis缓存淘汰算法,LRU算法,LRU算法讲解

网友评论

      本文标题:算法_Simulated-Annealing_Python

      本文链接:https://www.haomeiwen.com/subject/pnorqttx.html