Code | 八数码和八皇后

import numpy as np
import copy
import random
import math

target = [[1, 2, 3], [8, 0, 4], [7, 6, 5]]
state = [[1, 3, 0], [8, 2, 4], [7, 6, 5]]

state_queen = [random.randint(0, 7) for i in range(8)]
state_queen = np.eye(8)[state_queen].T

def loss(state, target=None, s=1):
    #八数码
    state = np.array(state)
    if s==1:
        target = np.array(target)
        loss_sum = 0
        for i in range(9):
            loss_sum += sum(sum(abs(np.argwhere(state == i) - np.argwhere(target == i))))
    #八皇后
    if s==0:
        attack_pair = 0
        for i in range(8):
            for j in range(8):
                if state[j][i] == 1:
                    attack_pair += sum(state[j])-1 + sum(state.T[i])-1
                    k = i-1
                    l = j-1
                    while k >= 0 and l >= 0:
                        attack_pair += state[l][k]
                        k = k-1
                        l = l-1
                    k = i + 1
                    l = j + 1
                    while k <= 7 and l <= 7:
                        attack_pair += state[l][k]
                        k = k + 1
                        l = l + 1
                    k = i - 1
                    l = j + 1
                    while k >= 0 and l <= 7:
                        attack_pair += state[l][k]
                        k = k - 1
                        l = l + 1
                    k = i + 1
                    l = j - 1
                    while k <= 7 and l >= 0:
                        attack_pair += state[l][k]
                        k = k + 1
                        l = l - 1

        loss_sum = attack_pair/2

    return loss_sum


def generating_sons(state, s=1):
    state = np.array(state)
    sons = []
    if s == 1:
        hole_loc = np.squeeze(np.argwhere(state == 0))
        if hole_loc[0]-1 >= 0:
            new_son = copy.deepcopy(state)
            new_son[hole_loc[0]][hole_loc[1]] = new_son[hole_loc[0]-1][hole_loc[1]]
            new_son[hole_loc[0]-1][hole_loc[1]] = 0
            sons.append(copy.deepcopy(new_son))
        if hole_loc[1]-1 >= 0:
            new_son = copy.deepcopy(state)
            new_son[hole_loc[0]][hole_loc[1]] = new_son[hole_loc[0]][hole_loc[1]-1]
            new_son[hole_loc[0]][hole_loc[1] - 1] = 0
            sons.append(copy.deepcopy(new_son))
        if hole_loc[0]+1 <= 2:
            new_son = copy.deepcopy(state)
            new_son[hole_loc[0]][hole_loc[1]] = new_son[hole_loc[0]+1][hole_loc[1]]
            new_son[hole_loc[0]+1][hole_loc[1]] = 0
            sons.append(copy.deepcopy(new_son))
        if hole_loc[1]+1 <= 2:
            new_son = copy.deepcopy(state)
            new_son[hole_loc[0]][hole_loc[1]] = new_son[hole_loc[0]][hole_loc[1]+1]
            new_son[hole_loc[0]][hole_loc[1] + 1] = 0
            sons.append(copy.deepcopy(new_son))
    if s == 0:
        for i in range(8):
            for j in range(8):
                if state[j][i] == 1:
                    new_son = copy.deepcopy(state)
                    new_son[j][i] = 0
                    for k in range(1, 8):
                        new_son[(j+k) % 8][i] = 1
                        sons.append(copy.deepcopy(new_son))
                        new_son[(j+k) % 8][i] = 0
    return sons


def randomly_generate_one_state(state=None):
    if state is None:
        state_queen = [random.randint(0, 7) for i in range(8)]
        state_queen = np.eye(8)[state_queen].T
        return state_queen
    for i in range(random.randint(0, 100)):
        sons = generating_sons(state)
        son = randomly_choose_one_son(sons)
        state = son
    return state


def randomly_choose_one_son(sons):
    return sons[random.randint(0, len(sons)-1)]


def climbing_mountain_steepest(state, target=None, s=1):
    state = copy.deepcopy(state)
    target = copy.deepcopy(target)
    count = 0
    while loss(state, target, s) != 0:
        sons = generating_sons(state, s)
        loss_sons = []
        for son in sons:
            loss_sons.append(loss(son, target, s))
        state = sons[np.argmin(np.array(loss_sons))]
        count += 1
        if count > 1000:
            return False
    return state, count


def climbing_mountain_random_better(state, target=None, s=1):
    state = copy.deepcopy(state)
    target = copy.deepcopy(target)
    count = 0
    while loss(state, target, s) != 0:
        inner_count = 0
        if count > 1000:
            return False
        sons = generating_sons(state, s)
        son = randomly_choose_one_son(sons)
        while loss(son, target, s) > loss(state, target, s):
            inner_count += 1
            son = randomly_choose_one_son(sons)
            if inner_count > 300:
                return False
        state = son
        count += 1
    return state, count


def climbing_mountain_random_restart():
        state = randomly_generate_one_state()
        out = climbing_mountain_steepest(state, s=0)
        if out is not False:
            step = out[1]
        else:
            step = 0
        while out is False:
            step += 1000
            state = randomly_generate_one_state()
            out = climbing_mountain_steepest(state, s=0)
        step += out[1]
        return out, step


def sim_annealing(state, target=None, s=1, init_temp=1000, temp_iter_num=1, cooling_factor=0.95):
    state = copy.deepcopy(state)
    target = copy.deepcopy(target)
    T = init_temp
    count = 0
    step = 0
    while loss(state, target, s) != 0:
        sons = generating_sons(state, s)
        son = randomly_choose_one_son(sons)
        delta_loss = loss(state, target, s) - loss(son, target, s)
        count += 1
        if count > 4000:
            return False
        if delta_loss > 0:
            state = son
            T = T*cooling_factor
            step += 1
        else:
            prob = math.exp(delta_loss/T)
            T = T * cooling_factor
            if prob > random.random():
                state = son
                step += 1
            else:
                continue
    return state, step

def main():
    num_rb_counter = [0, 0]
    num_sa_counter = [0, 0]
    num_sp_conter = [0, 0]

    queen_rb_counter = [0, 0]
    queen_sa_counter = [0, 0]
    queen_sp_conter = [0, 0]
    queen_rr_counter = [0, 0]
    for i in range(1000):
        state = randomly_generate_one_state(target)
        rb = climbing_mountain_random_better(state, target)
        sp = climbing_mountain_steepest(state, target)
        sa = sim_annealing(state, target)
        if rb is not False:
            num_rb_counter[0] += 1
            num_rb_counter[1] += rb[1]
        if sp is not False:
            num_sp_conter[0] += 1
            num_sp_conter[1] += sp[1]
        if sa is not False:
            num_sa_counter[0] += 1
            num_sa_counter[1] += sa[1]

        state = randomly_generate_one_state()
        rb_q = climbing_mountain_random_better(state, s=0)
        sp_q = climbing_mountain_steepest(state, s=0)
        sa_q = sim_annealing(state, s=0)
        rr_q = climbing_mountain_random_restart()
        if rb_q is not False:
            queen_rb_counter[0] += 1
            queen_rb_counter[1] += rb_q[1]
        if sp_q is not False:
            queen_sp_conter[0] += 1
            queen_sp_conter[1] += sp_q[1]
        if sa_q is not False:
            queen_sa_counter[0] += 1
            queen_sa_counter[1] += sa_q[1]
        if rr_q is not False:
            queen_rr_counter[0] += 1
            queen_rr_counter[1] += rr_q[1]

        print(i, [num_sp_conter, num_rb_counter, num_sa_counter],
              [queen_sp_conter, queen_rb_counter, queen_sa_counter, queen_rr_counter])

main()

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值