人工智能-模拟退火算法解决八数码问题-python源码

问题描述:

在一个3*3的方棋盘上放置着1,2,3,4,5,6,7,8八个数码,每个数码占一格,且有一个空格。这些数码可以在棋盘上移动,其移动规则是:与空格相邻的数码方格可以移入空格。现在的问题是:对于指定的初始棋局和目标棋局,给出数码的移动序列。该问题称八数码难题或者重排九宫问题。

 

01

算法解决流程图为:

01

源代码为:

import numpy as np
import random
import time
import math
import copy


# 模拟退火算法解决八皇后问题
# 八数码初始化函数,返回一个初始状态和一个目标状态,这里0代表八数码中的空格
def init():
    init_state = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8])
    target_state = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8])
    np.random.shuffle(init_state)
    np.random.shuffle(target_state)
    init_state = np.reshape(init_state, (3, 3))
    target_state = np.reshape(target_state, (3, 3))
    return init_state, target_state


# 计算当前状态和目标状态下的曼哈顿距离
def compute_manhattan_distance(init_state, target_state):
    total_distance = 0
    for i in range(1, 9):
        (init_row, init_column) = np.where(init_state == i)
        (target_row, target_column) = np.where(target_state == i)
        total_distance += abs(target_row - init_row) + abs(target_column - init_column)
    return int(total_distance)


# 计算接下来所有可以移动的方向,因为空白方块可能处于边界
def get_direction(state):
    current_state = state.copy()
    coord_cache = {}
    zero_row, zero_column = np.where(current_state == 0)
    if zero_row - 1 >= 0:  # 如果空白方块在最上边则不能往上移,下面同理
        up_row, up_column = zero_row - 1, zero_column
        coord_cache["up"] = [up_row, up_column]
    if zero_row + 1 <= 2:
        down_row, down_column = zero_row + 1, zero_column
        coord_cache["down"] = [down_row, down_column]
    if zero_column - 1 >= 0:
        left_row, left_column = zero_row, zero_column - 1
        coord_cache["left"] = [left_row, left_column]
    if zero_column + 1 <= 2:
        right_row, right_column = zero_row, zero_column + 1
        coord_cache["right"] = [right_row, right_column]
    return coord_cache


# 随机产生一个新的解
def random_adjust(state, target_state):
    # 随机选择可以移动的方向把坐标取出来
    current_state = state.copy()
    direction = get_direction(state)
    cache = list(direction.keys())
    index = random.randrange(0, len(cache))
    row, column = direction[cache[index]]
    row, column = int(row), int(column)  # fix bug,这里的row,column等是列表,直接作为索引使用会报错,转换为int类型
    # 开始随机调整
    zero_row, zero_column = np.where(current_state == 0)
    zero_row, zero_column = int(zero_row), int(zero_column)
    temp = current_state[row][column]
    current_state[zero_row][zero_column] = temp
    current_state[row][column] = 0
    distance = compute_manhattan_distance(current_state, target_state)
    return current_state, distance


# 模拟退火算法
def sa_algorithm(temperature, temperature_min, r, L):
    """
    :param temperature: 初始温度值
    :param r:用于控制降温的快慢
    :param temperature_min:温度下限,低于这个温度还没有找到最优解算法结束
    :param L:每个温度的迭代次数
    :return:bool
    """
    state, target_state = init()
    print("目标状态为:\n", target_state)
    while temperature > temperature_min:
        for j in range(L):  # 每个温度循环L次
            current_manhattan_distance = compute_manhattan_distance(state, target_state)
            print("当前状态为:\n", state)
            print("当前状态的曼哈顿距离为:", current_manhattan_distance)
            if current_manhattan_distance == 0:  # 如果曼哈顿距离为零,则代表就是目标状态了
                return True
            new_state, new_manhattan_distance = random_adjust(state, target_state)  # 随机调整得到一个新的解和这个解的曼哈顿距离
            print("随机产生的新解状态为:\n", new_state)
            print("随机产生新解的曼哈顿距离为:", new_manhattan_distance)
            delta_manhattan_distance = current_manhattan_distance - new_manhattan_distance
            if delta_manhattan_distance > 0:  # 如果新解更好 接受
                print("这是一个更好的解,直接接收")
                state = new_state
            else:
                if math.exp(delta_manhattan_distance / temperature) > random.random():  # 如果新解更差 以模拟退火的概率接受它
                    print("当前接收更差解的概率为:", math.exp(delta_manhattan_distance / temperature))
                    print("这是一个更差的解,但是被接收了")
                    state = new_state
        temperature = temperature * r  # 模拟退火,温度衰减
    return False


def SA_algorithm_test(temperature, temperature_min, r, L, num):
    tic = time.time()
    success_case = 0
    fail_case = 0
    for i in range(num):
        if sa_algorithm(temperature, temperature_min, r, L):
            success_case += 1
            # time.sleep(10000)
            print("第{0}个例子找到了最优解".format(i))
        else:
            fail_case += 1
            print("第{0}个例子失败".format(i))
    toc = time.time()
    print("{0}个例子中成功解决的例子为:{1}".format(num, success_case))
    print("{0}个例子成功解决的百分比为:{1}".format(num, success_case / num))
    print("{0}个例子中失败的例子为:{1}".format(num, fail_case))
    print("{0}个例子失败的百分比为:{1}".format(num, fail_case / num))
    print("{0}个例子运行算法所需的时间为:{1}秒".format(num, toc - tic))


SA_algorithm_test(temperature=5, temperature_min=0.001, r=0.8, L=150, num=100)

在实验参数为:T=5,T_min=0.001,L=100,R=0.99下,结果为:

01

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以为您介绍一下Python模拟退火算法解决旅行商问题。 旅行商问题(Traveling Salesman Problem,TSP)是指在所有城市之间建立完全图,每对城市之间有一条权值为正的边。旅行商要从某个城市出发,遍历所有城市一次后回到出发的城市,且使所走过的路程最短。这是一个NP难问题,因此需要采用一些启发式算法来求解。 模拟退火算法(Simulated Annealing,SA)是一种基于概率的全局优化算法,可以用于求解TSP问题。其基本思想是通过一定的概率规律,在搜索过程中跳出局部最优解,并逐渐降低温度以达到全局最优解。 下面是一个简单的Python代码实现,使用模拟退火算法解决TSP问题: ```python import random import math def distance(city1, city2): return math.sqrt((city1[0] - city2[0]) ** 2 + (city1[1] - city2[1]) ** 2) def TSP(cities, T_init, T_end, alpha, iter_max): n = len(cities) cur_solution = list(range(n)) random.shuffle(cur_solution) cur_cost = sum(distance(cities[cur_solution[i]], cities[cur_solution[i-1]]) for i in range(n)) T = T_init while T > T_end: for i in range(iter_max): new_solution = cur_solution.copy() a = random.randint(0, n-1) b = random.randint(0, n-1) new_solution[a], new_solution[b] = new_solution[b], new_solution[a] new_cost = sum(distance(cities[new_solution[i]], cities[new_solution[i-1]]) for i in range(n)) delta_cost = new_cost - cur_cost if delta_cost < 0 or math.exp(-delta_cost/T) > random.random(): cur_solution = new_solution.copy() cur_cost = new_cost T *= alpha return cur_cost, cur_solution if __name__ == '__main__': cities = [(0, 0), (1, 2), (3, 1), (5, 2), (6, 4), (4, 6), (1, 5), (2, 3)] T_init = 100 T_end = 0.1 alpha = 0.99 iter_max = 1000 cost, solution = TSP(cities, T_init, T_end, alpha, iter_max) print('最短路径长度为', cost) print('最短路径为', solution) ``` 该代码定义了一个`distance`函数用于计算两个城市之间的距离,以及一个`TSP`函数用于求解TSP问题。其中,`cities`参数是一个城市列表,`T_init`和`T_end`分别是初始温度和最终温度,`alpha`是温度下降系数,`iter_max`是每个温度下的迭代次数。代码中使用了随机交换两个城市的方法来产生新解,并使用Metropolis准则来决定是否接受新解。最终返回的是最短路径长度和最短路径的顺序。 以上就是一个简单的Python模拟退火算法解决TSP问题的例子,希望能够对您有所帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值