数学建模|A*算法实现单层电路布线(python)

2020.06.20更新了一下走过路径的判断,之前的代码考虑不周,产生覆盖现象,欢迎各位指导交流。
A*算法简介这里就不多说了传送门


author:xiao黄
缓慢而坚定的生长


题目:假设采用一层金属布线,那么已经布线的方格被锁定,不允许其它线路穿过,否则会形成短路。图1所示为采用一层金属的通道布线例子,布线空间为4x7,空间上下沿的数字分别对应方格的引脚编号,编号相同的引脚需要连接起来。请针对此一层金属的“通道布线”问题完成建模和求解,并回答如下问题:在何种情况下,一层金属通道布线问题无解。
测试例子:
在这里插入图片描述

代码:

#需要进行抽象化的有:节点(属性有:x y坐标  父节点  g及h )  地图(属性有高度 宽度  数据(数据中有可通行路径与障碍两种))
#A_star :
# open_list (存放待测试的点,刚开始有start加入list,后面每一个current的相邻点(不能位于colse_list中且不是终点)要放到open_list中) 表示已经走过的点
# close_list(存放已测试的点,已经当过current的点,就放到close_list中) 存放已经探测过的点,不必再进行探测
# current 现在正在测试的点,要计算current周围的点的代价f  经过current后要放到close_list中 将openlist代价f最小的node当作下一个current
# start_point end_point

#初始化地图  openlist closelist node
#将start点放入openlist中
#while(未达到终点):
#取出 openlist 中的点 将这个点设置为current 并放入closelist中
#for node_near in(current的临近点)
#if(current的临近点 node_near 不在closelist中且不为障碍):
#计算 node_near 的f(f=g+h)大小
# if( node_near 不在 openlist 中)
# 将 node_near 放入 openlist,并将其父节点设置为current 然后将f值设置为计算出的f值
# else if( node_near 在 openlist 中)
#  if(计算出的f大于在openlist中的f)
#    不动作
#  else if(计算出的f小于等于在openlist中的f)
#     将 openlist 中的 node_near 的f值更新为计算出的新的更小的f值 并将父节点设置为current
#返回并继续循环

import sys
#将地图中的点抽象化成类
class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __eq__(self, other): #函数重载
        if((self.x == other.x )and (self.y == other.y)):
            return  1
        else:
            return 0

#通过列表实现的地图的建立
class map_2d:
    def __init__(self,height,width):
        self.height = height
        self.width = width
        self.data = []
        self.data = [[0 for i in range(width)] for j in range(height)]

    def map_show(self):
        # 显示
        for i in range(self.height):
            for j in range(self.width):
                print(self.data[i][j], end=' ')
            print()

    def obstacle(self,obstacle_x,obstacle_y):
        # 设置障碍
        self.data[obstacle_x][obstacle_y]=1

    def end_draw(self,point,mark): # 这里要改 mark
        self.data[point.x][point.y] = mark

#A*算法的实现
class A_star:
    # 设置node
    class Node:
        def __init__(self, point, endpoint, g):
            self.point = point  # 自己的坐标
            self.endpoint = endpoint  # 自己的坐标
            self.father = None  # 父节点
            self.g = g  # g值
            self.h = (abs(endpoint.x - point.x) + abs(endpoint.y - point.y)) * 10  # 计算h值
            self.f = self.g + self.h

        #寻找临近点
        def search_near(self,ud,rl):  # up  down  right left
            nearpoint = Point(self.point.x + rl, self.point.y + ud)
            nearnode = A_star.Node(nearpoint, self.endpoint, self.g + 1)
            return nearnode


    def __init__(self,start_point,end_point,map):#需要传输到类中的,在此括号中写出
        self.path=[]
        self.close_list=[] #存放已经走过的点
        self.open_list=[] #存放需要进行探索的点
        self.current = 0 #现在的node
        self.start_point=start_point
        self.end_point=end_point
        self.map = map #所在地图

    def select_current(self):
        min=10000000
        node_temp = 0
        for ele in self.open_list:
            if ele.f < min:
                min = ele.f
                node_temp = ele
        self.path.append(node_temp)
        self.open_list.remove(node_temp)
        self.close_list.append(node_temp)
        return node_temp

    def isin_openlist(self,node):
        for opennode_temp in self.open_list:
            if opennode_temp.point == node.point:
                return opennode_temp
        return 0

    def isin_closelist(self,node):
        for closenode_temp in self.close_list:
            if closenode_temp.point == node.point:
                return 1
        return 0

    def is_obstacle(self,node):
        # 判断是否障碍
        # print(self.map.data[node.point.x][node.point.y]) # 超出索引
        if self.map.data[node.point.x][node.point.y] != 0 :
            return  1
        return  0

    def near_explore(self,node):
        ud = 1
        rl = 0
        node_temp = node.search_near(ud,rl) 
        if node_temp.point == end_point:
            return 1
        elif self.isin_closelist(node_temp):
            pass
        elif self.is_obstacle(node_temp):
            pass
        elif self.isin_openlist(node_temp) == 0:
            node_temp.father = node
            self.open_list.append(node_temp)
        else:
            if node_temp.f < (self.isin_openlist(node_temp)).f:
                self.open_list.remove(self.isin_openlist(node_temp))
                node_temp.father = node
                self.open_list.append(node_temp)

        ud = -1
        rl = 0
        node_temp = node.search_near(ud,rl) 
        if node_temp.point == end_point:
            return 1
        elif self.isin_closelist(node_temp):
            pass
        elif self.is_obstacle(node_temp):
            pass
        elif self.isin_openlist(node_temp) == 0:
            node_temp.father = node
            self.open_list.append(node_temp)
        else:
            if node_temp.f < (self.isin_openlist(node_temp)).f:
                self.open_list.remove(self.isin_openlist(node_temp))
                node_temp.father = node
                self.open_list.append(node_temp)

        ud = 0
        rl = 1
        node_temp = node.search_near(ud,rl) 
        if node_temp.point == end_point:
            return 1
        elif self.isin_closelist(node_temp):
            pass
        elif self.is_obstacle(node_temp):
            pass
        elif self.isin_openlist(node_temp) == 0:
            node_temp.father = node
            self.open_list.append(node_temp)
        else:
            if node_temp.f < (self.isin_openlist(node_temp)).f:
                self.open_list.remove(self.isin_openlist(node_temp))
                node_temp.father = node
                self.open_list.append(node_temp)

        ud = 0
        rl = -1
        node_temp = node.search_near(ud,rl) 
        if node_temp.point == end_point:
            return 1
        elif self.isin_closelist(node_temp):
            pass
        elif self.is_obstacle(node_temp):
            pass
        elif self.isin_openlist(node_temp) == 0:
            node_temp.father = node
            self.open_list.append(node_temp)
        else:
            if node_temp.f < (self.isin_openlist(node_temp)).f:
                self.open_list.remove(self.isin_openlist(node_temp))
                node_temp.father = node
                self.open_list.append(node_temp)
        return 0

if __name__ == '__main__':
    width = int(input()) # 宽 ->行
    length = int(input()) # 长 ->列  # 注意需要比原始数据多1列
    # 缺少边缘判断
    ss = map_2d(width,length)

    Upper_pin = list(map(int,input().split())) # 上引脚 
    Lower_pin = list(map(int,input().split())) # 下引脚 
    a = Upper_pin.copy()
    b = Lower_pin.copy()
    if Upper_pin != sorted(a) or Lower_pin != sorted(b):
        print('单层无解')
    else:
        l = len(Upper_pin) # 一共循环多少次
        i = 0
        m = 0 #步数统计
        for i in range(l):
            start_point = Point(0, Upper_pin[i]-1)
            end_point = Point(width-1, Lower_pin[i]-1)
            ss.end_draw(end_point,i+1)
            ss.end_draw(start_point,i+1)

            #初始化设置A*
            a_star = A_star(start_point,end_point,ss)
            start_node = a_star.Node(start_point,end_point,0)
            a_star.open_list.append(start_node)

            flag = 0 #到达终点的标志位

            #进入循环
            while  flag != 1 :
                a_star.current = a_star.select_current()#从openlist中选取一个node
                flag = a_star.near_explore(a_star.current)#对选中的node进行周边探索
                m = m + 1
                
            #画出地图路径
            for node_path in a_star.path:
                ss.end_draw(node_path.point,i+1)

        print('最优解的步数:', m + l)
        ss.map_show()

运行结果:
在这里插入图片描述

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xiao黄

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值