Prim完成,。附简易拓扑图。
main文件
import copy
import math
import turtle
import numpy as np
import pandas as pd
from Lions import Lions
import sys
import matplotlib.pyplot as plt
import benchmarks
from CS import CS
class Node:
x = y = 0
demand = 0
name = -2
father = None
next = None
e_length = 0
goat_ne = 0 # 羊邻居
lion_ne = 0 # 师邻居
out_degree = 0
is_A = True # False for B dot
state = True # True for work well
well = (1 - 0.005) * (1 - 0.005) # 可靠性
def __init__(self, x, y, name, demand):
self.x = x
self.y = y
self.name = name
self.demand = demand
def release(self):
self.father = None
'''
del self.x
del self.y
del self.demand
del self.name
del self.father
del self.next
del self.e_length
'''
# del self.out_degree
# del self.is_A # False for B dot
# del self.state # True for work well
# del self.well # 可靠性
class Graph:
arc_node = list()
class Link:
head = None
tail = None
data = 1e05
next = None
def __init__(self, head=None, tail=None, data=1E05, nex=None):
self.head = head
self.tail = tail
self.data = data
self.next = nex
def release(self):
self.head = None
self.tail = None
del self.head
del self.tail
del self.data
del self.next
def copy1(self):
return Link(self.head, self.tail, self.data, None)
def distance(node1: Node, node2: Node): # calculate the distance of two nodes
return math.sqrt((node1.x - node2.x) ** 2 + (node1.y - node2.y) ** 2)
def draw(graph):
turtle.penup()
turtle.screensize(200, 200)
for node in graph:
turtle.goto(node.x / 4, node.y / 4)
turtle.pendown()
turtle.dot(10)
turtle.penup()
def draw_graph(tree):
T = tree.T
# 画整体拓扑
T1 = set()
turtle.penup()
turtle.screensize(3000, 3000)
for node in T:
node_p = node
turtle.goto(node_p.x, node_p.y)
turtle.pendown()
while node_p:
turtle.goto(node_p.x, node_p.y)
if not node_p.is_A:
turtle.dot(20, "green")
else:
turtle.dot(30, "black")
turtle.goto(X0[int(node_p.name), 1], X0[int(node_p.name), 2])
turtle.dot(40, "blue")
turtle.goto(node_p.x, node_p.y)
turtle.hideturtle() # 隐藏画笔
turtle.write(str(int(node_p.name)), font=("宋体", 17, "bold")) # 输出文字
if node_p in T1:
break
else:
T1.add(node_p)
node_p = node_p.father
turtle.penup()
# 突出主线
if not tree.last_node:
turtle.done()
return
node = tree.last_node
turtle.goto(node.x, node.y)
turtle.pendown()
turtle.pensize(10)
turtle.pencolor("red")
while node:
turtle.goto(node.x, node.y)
node = node.father
# turtle.done()
turtle.clearscreen()
def creat_link(graph): # 创建一个全连接的边的单链表
p = Link()
for m in range(len(graph)):
for n in range(m + 1, len(graph)):
temp = Link(graph[m], graph[n], distance(graph[m], graph[n]), p)
p = temp
return p
def release_link(head):
while head:
tp = head.next
head.release()
head = tp
def sort(head: Link):
start = Link()
p = start
p.data = 1.11
p2 = head
while p2:
p3 = head
temp = Link()
while p3:
if temp.data > p3.data > p.data:
temp = p3
p3 = p3.next
p.next = copy1(temp)
p = p.next
p2 = p2.next
return start
'''
def sort(head: Link):
p = last = head
while p:
p2 = last2 = head
while p2 != p:
if p2.data > p.data:
last.next = p.next
last2.next = p
p.next = p2
p = last.next
break
last2 = p2
p2 = p2.next
if p2 == p:
last = p
p = p.next
print(p.data)
print(p2.data)
print()
return head
'''
def prim(e_head: Link, num_v):
p = e_head.next
set1 = {p.head, p.tail}
p.tail.father = p.head
while len(set1) != num_v:
while p:
if p.tail in set1 and p.head not in set1 \
or p.tail not in set1 and p.head in set1:
head = p.head if p.head in set1 else p.tail # judge which is head node
tail = p.tail if head == p.head else p.head
tail.father = head
set1.add(tail)
p = e_head.next
break
p = p.next
class Tree:
T = set()
main_path = set() # 主线
last_node = None
cross_set = set()
cost_table = np.zeros(6) # 总价 主开关 主线 A支线 B支线 负荷开关和支线开关
Root = None
def __init__(self, graph):
T1 = set()
for node in graph:
father = node.father
while father:
father = father.father
if father not in T1:
T1.add(father)
for node in graph:
if node not in T1:
self.T.add(node)
while node:
if not node.father:
self.Root = node
node = node.father
self.cost_table = np.zeros(6)
def release(self):
for node in self.T:
p = node
while p:
temp = p.father
p.release()
p = temp
self.T.clear()
self.main_path.clear() # 主线
self.cross_set.clear()
'''
del self.T
del self.main_path
del self.cross_set
del self.last_node
del self.cost_table
'''
def re_root(self, root: Node): # 修改根节点 同时更改主线
self.Root = root
father = root.father
root.father = None
you = root
while father:
g_father = father.father
father.father = you
you = father
father = g_father
'''
c = 0
for node in self.T:
tp = node
string = ''
while tp is not None:
temp2 = tp.father
temp = tp
string = string + str(tp.name) + '->'
tp = tp.father
print(string)
g = len(self.T)
print(c)
'''
# 生成主线 main_path
main_stream = 0
for node in self.T:
father = node.father
temp_stream = 0
while father:
temp_stream = temp_stream + father.demand
father = father.father
if main_stream < temp_stream:
main_stream = temp_stream
main_node = node # 储存位于主线的末端节点
self.last_node = main_node
while main_node:
self.main_path.add(main_node)
main_node = main_node.father
# 查找分支节点
set1 = set()
for node in self.T:
p = node
while p:
if p in set1:
self.cross_set.add(p)
break
else:
set1.add(p)
p = p.father
# 计算节点下游负荷节点数,便于算支线造价
for node in self.T:
p = node
while p.father:
if p.is_A:
p.father.out_degree = p.father.out_degree + p.out_degree + 1
else:
p.father.out_degree = p.father.out_degree + p.out_degree
p = p.father
# 算造价: 总价 主开关 主线 A支线 B支线 负荷开关和支线开关
def cost(self, price):
# 主线开关
self.cost_table[1] = price[1] * (len(self.main_path) - 1)
# 主线
node = self.last_node
while node.father:
temp = distance(node, node.father) * price[2]
self.cost_table[2] = self.cost_table[2] + temp
node = node.father
# A、B支线
set1 = self.T.copy()
set1.remove(self.last_node)
m_path = set()
for node in self.main_path:
m_path.add(node.name)
for node in set1:
p = node
while p.name not in m_path:
if p.father.out_degree < 3:
self.cost_table[3] = self.cost_table[3] + distance(p, p.father) * price[3]
else:
self.cost_table[4] = self.cost_table[4] + distance(p, p.father) * price[4]
p = p.father
# 支线开关
self.cost_table[5] = self.cost_table[5] + size * price[5]
t_set = set()
for node in self.T:
p = node
while p not in t_set and p.father:
t_set.add(p)
if p.father in self.cross_set:
self.cost_table[5] = self.cost_table[5] + price[5]
p = p.father
# 总价
self.cost_table[0] = np.sum(self.cost_table[1:])
# print(self.cost_table)
def cal_well(self, rate):
for node in self.T:
p = node
while p:
pp = p
while pp.father:
p.well = p.well * (1 - distance(pp, pp.father) * 0.002)
if pp.father in self.cross_set:
p.well = p.well * (1 - 0.002)
pp = pp.father
# print(str(p.name) + ':'+str(p.well))
p = p.father
def create_graph(X_in,n): # 创建拓扑
graph1 = list()
for k in range(len(X_in)):
graph1.append(Node(X_in[k, 1], X_in[k, 2], X_in[k, 0], X_in[k, 3]))
if k >= size:
graph1[k].is_A = False
l_head = creat_link(graph1)
l_head = sort(l_head)
prim(l_head, n)
T0 = Tree(graph1) # 双亲表示法
T0.re_root(graph1[0])
release_link(l_head)
del l_head
return T0,graph1
def release_graph(T0,graph1):
# 析构
T0.release()
graph1.clear()
# print(sys.getrefcount(p))
del T0
def fitness(X_in,n):
T0,graph1 = create_graph(X_in,n)
# 适应度函数
Fitness = np.zeros((n - size, 2)) # 羊 狮
set1 = set()
set1.add(T0.Root)
for node in T0.T:
p = node
while p:
if p not in set1:
set1.add(p)
if not p.is_A and p.father.is_A:
Fitness[int(p.name - size), 0] = Fitness[int(p.name - size), 0] + 1
if not p.father.is_A:
if p.is_A:
Fitness[int(p.father.name - size), 0] = Fitness[int(p.father.name - size), 0] + 1
else:
Fitness[int(p.father.name - size), 1] = Fitness[int(p.father.name - size), 1] + 1
Fitness[int(p.name - size), 1] = Fitness[int(p.name - size), 1] + 1
p = p.father
set1.clear()
release_graph(T0, graph1)
return Fitness
def oj_fun(X_iter, n, iter_):
T0,graph1= create_graph(X_iter, n)
T0.cost(price0)
if iter_ % 10 == 0:
pass
# draw_graph(T0)
# print(T0.cost_table)
# T0.cal_well(0.002)
L = np.sum(np.sqrt(((X_iter[:size, 1] - X0[:, 1]) ** 2 + (X_iter[:size, 2] - X0[:, 2]) ** 2)))
Y = T0.cost_table[0] + price0[3] * L # 最终造价
release_graph(T0,graph1)
# print(Y)
return Y
if __name__ == '__main__':
size = 48
price0 = [0, 56.8, 325.7, 188.6, 239.4, 2.6] # 0 主开关 主线 A支线 B支线 负荷开关和支线开关
dataframe = pd.read_excel("./myData.xlsx")
X0 = dataframe.values[:, 1:]
X = X0.copy()
'''
X = np.zeros((size, 4))
t = range(len(X))
X[:, 0] = t
X[:, 1:] = np.random.rand(size, 3) * 1000
dataframe = pd.DataFrame(data=X)
dataframe.to_excel("myData.xlsx")
'''
PopulationSize = math.floor(size * 3 / 2)
Iterations = 50
# [name, lb, ub, dim]
lb = np.min(X0[:, 1:2])
ub = np.max(X0[:, 1:2])
dim = 2
fmin, bestnest, convergence1 = Lions(oj_fun, lb, ub, dim, PopulationSize, Iterations,fitness)
plt.figure()
plt.plot(convergence1, color='deepskyblue', linestyle='--', label='CS')
plt.legend(loc=4)
plt.xlabel('迭代次数')
plt.ylabel('最优解')
plt.title('迭代对比图')
plt.show()
print('配电网问题,狮群算法找到的目标函数的最佳值是: ' + str(fmin))
Lions 文件
import math
import numpy as np
import pandas as pd
import random
def Lions(obj_fun, lb, ub, dim, n, N_IterTotal): # 一个一个来
"""
:param obj_fun: 目标函数
:param lb: 数值下限
:param ub: 数值上限
:param dim: 维度
:param n: 群体大小
:param N_IterTotal: 最大迭代次数
:return: fmin, bestnest, convergence
"""
dataframe = pd.read_excel("./myData.xlsx")
X0 = dataframe.values[:, 1:]
X = np.zeros((n, 4))
size = len(X0)
X[:size, :] = X0.copy()
for k in range(n):
X[k, 0] = k
# X[size:, 1:3] = np.random.rand(n - size, 2) * 1000
X[size:, 1:3] = X[:n - size, 1:3]+1
R = (ub - lb) / np.sqrt(n - size) / 2 # 狮群领域半径
best_X = X.copy() # 历史最优解
last_X = X.copy() # 上次迭代解
last_f_min = 1e7
best_f_min = 1e7
curve = list() # 目标函数值曲线
# Lb=[lb]*nd
# Ub=[ub]*nd
for iter_in in range(n - size):
for iter_ in range(N_IterTotal):
# 求函数值
f_min, Fitness = obj_fun(X, n, iter_)
case = np.random.rand(1)
best_f_min = np.min([f_min, last_f_min, best_f_min])
if f_min == best_f_min:
best_X = X.copy()
elif last_f_min == best_f_min:
best_X = last_X.copy()
if f_min > last_f_min and case < 0.85:
X = last_X.copy()
else:
last_f_min = f_min
curve.append(last_f_min)
last_X = X.copy() # 上次迭代解
# 更新解
dx_A = (np.random.rand(size, 2) - np.random.rand(size, 2)) * (ub - lb) / size
X[:size, 1:3] = X0[:, 1:3] + dx_A
n_goat = Fitness[iter_in,0]
n_lion = Fitness[iter_in,1]
dx_B = np.random.rand(2) - np.random.rand(2)
STEP1 = R
STEP2 = R * 0.25
if n_goat < 3: # 无羊群
X[iter_in + size, 1:3] = X[iter_in + size, 1:3] + dx_B * STEP1
else:
if n_lion == 0: # 有羊无狮群
X[iter_in + size, 1:3] = X[iter_in + size, 1:3] + dx_B * STEP2
else: # 有羊有狮群
case = np.random.rand(1)
if case < 0.6:
X[iter_in + size, 1:3] = X[iter_in + size, 1:3] + dx_B * STEP1
elif case < 0.84:
X[iter_in + size, 1:3] = X[iter_in+size+1, 1:3] + 1
else:
X[iter_in + size, 1:3] = X[iter_in + size, 1:3] + dx_B * STEP2
if iter_ % 10 == 0:
print(['第' + str(iter_in) + '.' + str(iter_) + '次迭代的结果为:' + str(last_f_min) + '--->' + str(case)])
if iter_in % 10 == 0:
pass
#print(['第' + str(iter_) + '.' + str(iter_in) + '次迭代的结果为:' + str(last_f_min) + '--->' + str(case)])
return best_f_min, best_X, curve