2022深圳杯B题1问python代码

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

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 10
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值