人工智能-爬山法解决八皇后问题-python源码

问题简述:

八皇后问题,一个古老而著名的问题,是回溯算法的典型案例。该问题由国际西洋棋棋手马克斯·贝瑟尔于 1848 年提出:在 8×8 格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。

01

算法的逻辑流程图如下所示:

八皇后爬山法流程图

源代码为:

import copy
import numpy as np
import random
import time


# 爬山法解决八皇后问题

# 八皇后初始化函数
def init():
    cache = {}
    m = np.zeros((8, 8), dtype=int)
    for i in range(0, 8):
        temp = random.randrange(0, 8)
        m[temp, i] = 1
        cache["queen" + str(i)] = [temp, i]
    return m, cache


# 计算当前状态碰撞数量
def compute_weight_single(coord_cache):
    weight = 0
    for i in range(0, 8):
        x, y = coord_cache["queen" + str(i)]
        for j in range(i + 1, 8):
            _x, _y = coord_cache["queen" + str(j)]
            if _x - x == j - i or _x - x == i - j:
                weight += 1
            if _x == x:
                weight += 1
    return weight


# 计算8X8的碰撞矩阵
def compute_weight_matrix(coord_cache):
    weight_matrix = np.zeros((8, 8))
    for i in range(0, 8):
        for j in range(0, 8):
            # fix bug
            # 此处需用dict.copy函数,直接写赋值会导致仅仅建立了一个引用,改变引用也会改变原来的值
            temp_coord_cache = coord_cache.copy()
            temp_coord_cache["queen" + str(i)] = [j, i]
            weight = compute_weight_single(temp_coord_cache)
            weight_matrix[j, i] = weight
    return weight_matrix


# 根据碰撞矩阵调整皇后的位置
def next_move(cache, weight_matrix):
    coord_cache = cache
    min = np.min(weight_matrix)
    for i in range(0, 8):
        for j in range(0, 8):
            if weight_matrix[j, i] == min:
                # 调整皇后的位置
                coord_cache["queen" + str(i)] = [j, i]
                return coord_cache


# 把当前的皇后状态画出来
def draw(coord_cache):
    m = np.zeros((8, 8), dtype=int)
    for i in range(8):
        row, column = coord_cache["queen" + str(i)]
        row, column = int(row), int(column)
        m[row][column] = 1
    return m


# 爬山算法
def climbing_algorithm():
    m, coord_cache = init()
    while True:
        weight = compute_weight_single(coord_cache)  # 计算当前状态的碰撞值
        # print("当前的八皇后状态为:\n", draw(coord_cache))
        # print("当前的八皇后状态的碰撞度为\n", weight)
        if weight == 0:  # 碰撞值为零,为目标状态,算法结束
            return True
        weight_matrix = compute_weight_matrix(coord_cache)  # 计算8*8的碰撞矩阵
        # print("当前的碰撞矩阵为:\n", weight_matrix)
        # 如果碰撞矩阵的最小值都大于等于当前状态的碰撞值,则不能找到一个更好的解
        if weight_matrix.min() >= weight:
            return False
        else:
            coord_cache = next_move(coord_cache, weight_matrix)  # 移动皇后


def climbing_algorithm_test(num):
    tic = time.time()
    success_case = 0
    fail_case = 0
    for i in range(num):
        if climbing_algorithm():
            print("第{0}个例子成功找到最优解".format(i))
            success_case += 1
        else:
            print("第{0}个例子失败".format(i))
            fail_case += 1
    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))


climbing_algorithm_test(10000)

 

测试结果:

各算法解决八皇后八数码成功率:

比较图

 

 

  • 3
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值