[Algorithm] Annealing algorithm + knapsack problem python

1. Concept

The simulated annealing algorithm adopts a process similar to physical annealing, first in a high temperature state, then gradually annealed, slowly cooled at each temperature, and finally reaches the physical ground state.

insert image description here

high temperatureEquivalent to algorithmic random search .
repeated annealingIt is a state transition, and then a local search of the algorithm .
cool downIt is time to find the optimal solution .

When heated, a force will be given to the small iron molecule balls, and they will roll freely on the curved surface. After cooling down, they may stop in a small groove (that is, to obtain a local optimal solution), but not necessarily the deepest pit (the deepest pit). optimal solution), so repeated heating is required.
insert image description here

Second, the advantages of the algorithm

1. Overcome the initial value dependence.
2. Overcome the situation of being trapped in a local optimal solution.

3. Basic process and formula

(1) initialization: Initial temperature t=t0, randomly generate initial state X0, let Xbest=X0, k=0; (
2) Repeat:
(2.1) Repeat:
(2.1.1) Generate a new state Xnew=Generate(Xk); // state generation function
(2.1.2) ifrandom[0,1] ≤ min{1, exp[-(f(Xnew)-f(X)) / tk]}
Xk = Xnew; f(Xk) = f(Xnew); // f(X) represents the objective function value of X
(2.2) Until the sampling stability criterion satisfies
(2.3) Cooling tk+1 =update(tk), and make k=k+1;
(3) Until the termination criterion of the algorithm is satisfied;
(4) Output the result

The formula in 2.1.2 corresponds to the coordinate system in the figure below:
whenf(Xk) >= f(Xnew), is the part corresponding to the function value greater than or equal to 1 (that is, the part of x>=0)
, and vice versa, it is the part of x<0.

insert image description here

4. Examples + python code

It is known that the load of the backpack is c=10, and there are n=5 items, and their weight and value are (2, 3, 5, 1, 4) and (2, 5, 8, 3, 6) respectively. Try to solve the knapsack problem using simulated annealing algorithm.

python code

Import package:

import random
import math
import numpy as np

1. Initialization

# 背包容量c, 有n个物品
# time 迭代次数, balance平衡次数
# best 记录全局最优  T 温度  rate退火率
# wsum 当前重量总和    vsum 当前价值总和
n = 5
T = 200.0
rate = 0.95
time = 10
balance = 100
global c, best, wsum, vsum
# best_way 记录全局最优解方案   now_way 记录当前解方案
best_way = [0] * n     # 将[0]复制了m遍,变成[0,0,...,0]
now_way=[0] * n

Add topic data:

weight = [2, 3, 5, 1, 4]
value = [2, 5, 8, 3, 6]

def init():
    global c, best
    c = 10
    best = -1
    produce()

2.1.1 State generation function

def produce():  # 用于产生新解
    while(1):
        for k in range(n):
            if(random.random() < 0.5):
                now_way[k] = 1
            else:
                now_way[k] = 0
        calc(now_way)
        if (wsum < c):
            break
        global best
        best = calc(now_way)
        cop(best_way, now_way, n)

2.1.2 Annealing process
Calculate the value of the current knapsack, compare whether it is a better solution, and accept it if it is! If the current solution is poor, calculate the probability P of acceptance according to the formula, and accept the solution if P is large.

def anneal():  # 退火函数
    global best, T, balance
    test = [0] * n
    value_current = 0     # 当前背包价值
    for i in range(balance):
        value_current = calc(now_way)    # 计算当前背包的价值
        cop(test, now_way, n)  # 记录当前方案
        ob = random.randint(0, n-1)   # 随机选取某个物品
        if (test[ob] == 1):# 在背包中则将其拿出,并加入其它物品
            put(test)
            test[ob] = 1
        else:
            if(random.random()< 0.5): #接受新解的概率
                test[ob] = 1
            else:
                get(test)
                test[ob] = 1
        value_new = calc(test)
        if(wsum > c):    # 超重,则跳过
            continue
        if (value_new > value_current): # 接受该解
            cop(now_way, test, n)
        if (value_new > best):
            best = value_new
            cop(best_way, test, n) # 更新全局最优
        else:  # 按一定的概率接受该解
            g = 1.0 * (value_new - value_current) / T
            if (random.random() < math.exp(g)): # 概率接受劣解
                cop(now_way, test, n)

3. The function used in the middle to take out and put items into the backpack, and the function to calculate the value of the backpack

def cop(a, b, len):   # 把 b数组的值赋值a数组
    for i in range(len):
        a[i] = b[i]

def calc(x):        # 计算背包价值
    global c, wsum
    vsum = 0
    wsum = 0
    for i in range(n):
        vsum += x[i] * value[i]
        wsum += x[i] * weight[i]
    return vsum

def put(x):     # 往背包随机放入物品
    while(1):
        ob = random.randint(0, n-1);
        if (x[ob] == 0):   # 当前情况下物品还不在包里面
            x[ob] = 1
            break

def get(x):     # 往背包随机拿出物品
    while(1):
        ob = random.randint(0, n-1);
        if (x[ob] == 1):
            x[ob] = 0
            break

4. Main function

if __name__ == '__main__':
    init()
    flag = 0;          # 找到最优解
    for i in range(time):
        anneal()
        T = T * rate   # 温度下降
    print('找到最终解:', best, '迭代次数', time);

    print('方案为:', best_way);

END

Guess you like

Origin blog.csdn.net/qq_51669241/article/details/129429542