实验3 hopfield实现八皇后问题

传送门(所有的实验都使用python实现)

实验1 BP神经网络实验

实验2 som网实验

实验3 hopfield实现八皇后问题

实验4 模糊搜索算法预测薄冰厚度

实验5 遗传算法求解tsp问题

实验6 蚁群算法求解tsp问题

实验7 粒子群优化算法求解tsp问题

实验8 分布估计算法求解背包问题

实验9 模拟退火算法求解背包问题

实验10 禁忌搜索算法求解tsp问题

 

一、实验目的

理解并使用hopfile算法

二、实验内容

用hopfile实现八皇后问题。

三、实验环境

使用Python3.0 在 eclipse进行编辑

四、实验步骤

实验3 hopfield实现八皇后问题

实验3 hopfield实现八皇后问题

实验3 hopfield实现八皇后问题

实验3 hopfield实现八皇后问题

实验3 hopfield实现八皇后问题

运行结果展示:

实验3 hopfield实现八皇后问题

棋盘展示:

实验3 hopfield实现八皇后问题

五、总结

实验表明Hopfield网络具有一定的不稳定性,虽然大多数时候能够收敛到一个可行解,但有时会出现能量函数的收敛结果依然较大,主要是因为sumA、sumB1、sumB2、sumB3、sumB4某个值不为0,只要这几个值均为0,则收敛的结果必为可行解。另外实验也发现A、B、C值的设定也影响较大,如果一旦没设定好,有可能根本就不收敛,一直迭代下去。

python源码

#coding:gbk
import random
import math
import turtle

u = [[0.0]*100 for i in range(100)]        #输入电压
v = [[0.0]*100 for i in range(100)]         #输出电压
que = [0.0]*10; pos=0;      #que数组与pos模拟队列,当连续25次的能量函数的方差为0就是稳定状态
A=100;B=100;C=100;     #能量系数     
n=0;  g=15;   n_=8.25;     # n为棋盘直径,g为是sigmoid函数的增益 n_为常量
class no:                       #该类记录每个点的坐标
    def __init__(self,x,y):
        self.x=x;
        self.y=y;
def draw(i ,j):              #画图函数   将坐标为(i,j)空格涂黑
    turtle.goto(i, j)
    turtle.pendown()
    turtle.begin_fill()
    turtle.color("black")
    turtle.forward(30)
    turtle.left(90)
    turtle.forward(30)
    turtle.left(90)
    turtle.forward(30)
    turtle.left(90)
    turtle.forward(30)
    turtle.left(90)
    turtle.end_fill()
    turtle.penup()
    
def process(x):      #算法实现函数   x为棋盘直径 
    global n,pos;
    n=x;
    init();
    co = 0;
    while checkEng()== 0:
        co+=1;
        for k in range(1,n+1):
            for l in range(1,n+1):
                i=random.randint(1,n);
                j=random.randint(1,n);
                u[i][j] = calcU(i, j);           #输入电压更新
                v[i][j] = calcV(i, j);              #输出电压更新
        if(co%5==0):           #每五次记录一次能量值
            que[pos]=calcEnergy();      #加入队列
            #print(co,"++",que[pos])
            pos+=1;
            pos%=5;
    print("迭代次数",co)
    print("最终能量")
    print(calcEnergy())
        
def checkEng():             #方差检查函数
    sum1=0.0;
    for i in range(5):
        sum1+=que[i];
    sum1/=5;
    cnt=0.0;
    for i in range(5):
        cnt+=math.pow(que[i]-sum1,2);
  #  print("cnt=",cnt);
    if(cnt/5==0):
        return 1;
    else:
        return 0;
def  init():                        #能量值初始化
    for i in range(1,n+1):
        for j in range(1,n+1):
            v[i][j]=random.random();
    for i in range(5):          #队列初始化
        que[i]=i;
    print("初始能量")
    print(calcEnergy())
def calcEnergy():               #能量值计算
    sumA=0.0;                      #sumA计算
    for i in range(1,n+1):
        for j in range(1,n+1):
            sumRow=0.0;
            for k in range(1,n+1):
                if(k!=j):
                    sumRow+=v[i][k];
            sumColumn=0.0;
            for k in range(1,n+1):
                if(k!=i):
                    sumColumn+=v[k][j];
            sumA+=(sumRow + sumColumn) * v[i][j];
    sumA *= A;                               
    sumB1 = 0.0;                           #sumB1计算
    for i in range(2,n+1):
        for j in range(1,i):
            sumDiagonal=0.0;
            for k in range(i-j+1,n+1):
                if(k!=i):
                    sumDiagonal += v[k][k - i + j];
            sumB1 += sumDiagonal * v[i][j];
    sumB1 *= B;               
    sumB2 = 0;                  #sumB2计算
    for i in range(1,n+1):
        for j in range(i,n+1):
            sumDiagonal=0.0;
            for k in range(1,n+i-j):
                if(k!=i):
                    sumDiagonal += v[k][k - i + j];
            sumB2 += sumDiagonal * v[i][j];
    sumB2 *= B;             
    sumB3 = 0;              #sumB3计算
    for i in range(1,n+1):
        for j in range(n-i+1,n+1):
            sumDiagonal=0.0;
            for k in range(i+j-n,n+1):
                if(k!=i):
                    sumDiagonal += v[k][i + j - k];
            sumB3 += sumDiagonal * v[i][j];
    sumB3 *= B;             
    sumB4 = 0;                  #sumB4计算
    for i in range(1,n):
        for j in range(1,n-i+1):
            sumDiagonal=0.0;
            for k in range(1,i+j-1):
                if(k!=i):
                    sumDiagonal += v[k][i + j - k];
            sumB4 += sumDiagonal * v[i][j];
    sumB4 *= B;          
    sumC = 0.0;                         #sumC计算
    for i in range(1,n+1):
        for j in range(1,n+1):
            sumC +=v[i][j];
    sumC=C*math.pow(sumC-n_,2);   
    #print("sumA=",sumA,"sumB1=",sumB1,"sumB2=",sumB2,"sumB3=",sumB3,"sumA=",sumA,"sumC=",sumC);       
    return 0.5 * (sumA + sumB1 + sumB2 + sumB3 + sumB4 + sumC);
def calcU(i,j):                         #输入电压计算
    sumA = 0.0;
    for k in range(1,n+1):
        if (k != j):
            sumA += v[i][k];
    for k in range(1,n+1):
        if (k != i):
            sumA += v[k][j];
    sumA *= A;
    sumR = 0.0;
    if (i - j > 0):
        for k in range(i-j+1,n+1):
            if (k != i):
                sumR += v[k][k - i + j];
    else:
        for k in range(1,n+i-j+1):
            if (k != i):
                sumR += v[k][k - i + j];
    sumR *= B;
    sumS = 0.0;
    if (i + j > n):
        for k in range(i+j-n,n+1):
            if (k != i):
                sumS += v[k][i + j - k];
    else:
        for k in range(1,i+j):
            if (k != i):
                sumS += v[k][i + j - k];
    sumS *= B;
    sumC = 0.0;
    for k in range(1,n+1):
        for l in range(1,n+1):
            sumC += v[k][l];
    sumC = C * (sumC - n_);
    return -(sumA + sumR + sumS + sumC);
def calcV(i,j):                #输出电压计算
    return 0.5 * (1 + math.tanh(g * u[i][j]));
def printResult():      #结果打印
    print("结果矩阵")
    p =[]               #将n个皇后的坐标存在序列中
    for i in range(1,n+1):
        for j in range(1,n+1):
            print(v[i][j],end=" ");     #打印该位置状态
            if(v[i][j]!=0):                     #如果有皇后,加入序列
                p.append(no(i,j));
        print("");
    ok = 1;                 
    for i in range(8):#对于加入的八个皇后的坐标进行暴力检查是否冲突
        t1=p[i];
        for j in range(8):
            t2=p[j];
            if(i==j):
                continue;
            if(t1.x+t1.y==t2.x+t2.y or t2.x-t1.x==t2.y-t1.y or t1.x==t2.x or t1.y==t2.y): #其中一项符合即为冲突
                ok=0;
    if(ok == 1):        #ok==1说明此次计算结果为正确
        print("right")
    else:
        print("wrong")
def drawResult():       #将8*8的棋盘画出来
  #  turtle.Turtle().screen.delay(0)
    turtle.speed(8)         #画笔速度
#    turtle.pensize(1)
    turtle.penup()
    turtle.color("black")       #黑色画笔
    for i in range(0,270,30):
        turtle.goto(0, i)
        turtle.pendown()
        turtle.forward(240)
        turtle.penup()
    turtle.left(90)
    for i in range(0,270,30):
        turtle.goto(i, 0)
        turtle.pendown()
        turtle.forward(240)
        turtle.penup()
    turtle.right(90)
    for i in range(1,n+1):      #将8个皇后的位置涂黑
        for j in range(1,n+1):
            if(v[i][j] != 0):
                draw((i-1)*30,(j-1)*30)
    turtle.hideturtle()     #隐藏画笔
    turtle.done()

#x = input();
x=8
process(int(x));        #执行算法
printResult();          #打印结果
drawResult();           #描绘棋盘