将下面代码中的粒子群算法改成蚁群算法，直接给我修改好的完整代码：# -*- coding: utf-8 -*-
import matplotlib
matplotlib.rcParams['font.sans-serif'] = ['SimHei']
matplotlib.rcParams['axes.unicode_minus'] = False
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Circle, Arc, Rectangle
from matplotlib.widgets import Button, RadioButtons
import random


class DrillLayoutApp:
    def __init__(self):
        self.points = []
        self.arrows = []
        self.start_point = None
        self.contour_type = 'Rectangle'

        self.fig, self.ax = plt.subplots()
        plt.subplots_adjust(left=0.3)
        self._init_ui()
        self.draw_contour(self.ax)

        self.fig.canvas.mpl_connect('button_press_event', self.on_press)
        self.fig.canvas.mpl_connect('button_release_event', self.on_release)

    def _init_ui(self):
        ax_radio = plt.axes([0.05, 0.5, 0.2, 0.3])
        self.radio = RadioButtons(ax_radio, ('Rectangle', 'Circle', 'Arc'))
        self.radio.on_clicked(self.contour_select)

        ax_clear = plt.axes([0.05, 0.4, 0.15, 0.05])
        self.btn_clear = Button(ax_clear, '清空布孔')
        self.btn_clear.on_clicked(self.clear_all)

        ax_auto = plt.axes([0.05, 0.33, 0.15, 0.05])
        self.btn_auto = Button(ax_auto, '自动布孔')
        self.btn_auto.on_clicked(self.auto_drill)

        ax_pso = plt.axes([0.05, 0.26, 0.15, 0.05])
        self.btn_pso = Button(ax_pso, '孔序规划')
        self.btn_pso.on_clicked(self.drill_sequence_plan)

    def draw_contour(self, ax):
        ax.clear()
        ax.set_aspect('equal')
        if self.contour_type == 'Rectangle':
            rect = Rectangle((0, 0), 6, 5, fill=False, color='black', linewidth=2)
            ax.add_patch(rect)
            ax.set_xlim(-1, 7)
            ax.set_ylim(-1, 6)
        elif self.contour_type == 'Circle':
            circ = Circle((3, 3), 3, fill=False, color='black', linewidth=2)
            ax.add_patch(circ)
            ax.set_xlim(-1, 7)
            ax.set_ylim(-1, 7)
        elif self.contour_type == 'Arc':
            arc = Arc((3, 0), 6, 6, theta1=0, theta2=180, color='black', linewidth=2)
            ax.add_patch(arc)
            ax.set_xlim(-1, 7)
            ax.set_ylim(-1, 4)
        ax.set_title(f'布孔界面 - {self.contour_type}')
        ax.grid(True)

    def on_press(self, event):
        if event.inaxes != self.ax:
            return
        if event.button == 1:
            self.start_point = (event.xdata, event.ydata)
        elif event.button == 3:
            if self.points:
                click_point = np.array([event.xdata, event.ydata])
                point_arr = np.array(self.points)
                dists = np.linalg.norm(point_arr - click_point, axis=1)
                min_index = np.argmin(dists)
                if dists[min_index] < 0.3:
                    self.points.pop(min_index)
                    self.arrows.pop(min_index)
                    self.update_plot()

    def on_release(self, event):
        if event.inaxes != self.ax or self.start_point is None:
            return
        if event.button == 1:
            end_point = (event.xdata, event.ydata)
            self.points.append(self.start_point)
            dx = end_point[0] - self.start_point[0]
            dy = end_point[1] - self.start_point[1]
            self.arrows.append((self.start_point, (dx, dy)))
            self.start_point = None
            self.update_plot()

    def update_plot(self):
        self.draw_contour(self.ax)
        if self.points:
            x, y = zip(*self.points)
            self.ax.plot(x, y, 'ro')
        for arrow in self.arrows:
            x0, y0 = arrow[0]
            dx, dy = arrow[1]
            self.ax.arrow(x0, y0, dx, dy, head_width=0.1, head_length=0.15, fc='blue', ec='blue')
            mid_x = x0 + dx / 2
            mid_y = y0 + dy / 2
            depth = np.hypot(dx, dy) * 3.0
            self.ax.text(mid_x, mid_y, f"{depth:.1f}m", fontsize=10, color='green', ha='center')
        self.fig.canvas.draw_idle()

    def clear_all(self, event=None):
        self.points.clear()
        self.arrows.clear()
        self.update_plot()

    def contour_select(self, label):
        self.contour_type = label
        self.clear_all()

    def calculate_total_distance_open(self, order, points):
   # """非闭合路径长度"""
        return sum(np.linalg.norm(np.array(points[order[i]]) - np.array(points[order[i+1]])) 
                for i in range(len(order)-1))
    
    def total_cost(self, order, points, alpha=1.0):
        """路径长度 + 平滑度综合代价"""
        total_length = sum(np.linalg.norm(np.array(points[order[i]]) - np.array(points[order[i+1]]))
                        for i in range(len(order)-1))

        smooth_cost = 0
        for i in range(1, len(order)-1):
            p0 = np.array(points[order[i-1]])
            p1 = np.array(points[order[i]])
            p2 = np.array(points[order[i+1]])
            v1 = p1 - p0
            v2 = p2 - p1
            norm1 = np.linalg.norm(v1)
            norm2 = np.linalg.norm(v2)
            if norm1 > 1e-6 and norm2 > 1e-6:
                cos_theta = np.dot(v1, v2) / (norm1 * norm2)
                smooth_cost += (1 - cos_theta)  # 越小越好，夹角越平缓
        total = total_length + alpha * smooth_cost
        return total


    def swap_operator(self, order):
        a, b = random.sample(range(len(order)), 2)
        order[a], order[b] = order[b], order[a]
        return order

    def pso_tsp_smooth_path(self, points, num_particles=50, max_iter=500, c1=1.5, c2=1.5, alpha=1.0):
        num_points = len(points)
        particles = []
        pbest = []
        pbest_cost = []

        for _ in range(num_particles):
            order = list(range(num_points))
            random.shuffle(order)
            particles.append(order)
            cost = self.total_cost(order, points, alpha)
            pbest.append(order[:])
            pbest_cost.append(cost)

        gbest = pbest[np.argmin(pbest_cost)][:]
        gbest_cost = min(pbest_cost)

        for iter in range(max_iter):
            for i in range(num_particles):
                new_order = particles[i][:]
                if random.random() < 0.9:
                    new_order = self.swap_operator(new_order)

                new_cost = self.total_cost(new_order, points, alpha)

                if new_cost < pbest_cost[i]:
                    pbest[i] = new_order[:]
                    pbest_cost[i] = new_cost

                if new_cost < gbest_cost:
                    gbest = new_order[:]
                    gbest_cost = new_cost

                if random.random() < c1 / (c1 + c2):
                    new_order = pbest[i][:]
                else:
                    new_order = gbest[:]

                particles[i] = new_order

            if iter % 50 == 0:
                print(f'迭代 {iter}: 当前总代价 = {gbest_cost:.2f}')

        return gbest, gbest_cost
    
    def drill_sequence_plan(self, event=None):
        if not self.points:
            print("无布孔点，无法规划！")
            return

        order, dist = self.pso_tsp_smooth_path(self.points, alpha=1.0)
        print(f'规划完成，最短路径总长：{dist:.2f} m')

        self.arrows.clear()
        for i in range(len(order)-1):
            p1 = self.points[order[i]]
            p2 = self.points[order[i+1]]
            dx = p2[0] - p1[0]
            dy = p2[1] - p1[1]
            self.arrows.append((p1, (dx, dy)))

        self.update_plot()

    def auto_drill(self, event=None):
        self.points.clear()
        self.arrows.clear()
        if self.contour_type == 'Rectangle':
            width, height = 6, 5
            for y in np.arange(0.5, height, 1):
                for x in np.arange(0.5, width, 1):
                    self.points.append((x, y))
                    self.arrows.append(((x, y), (0, 0.5)))
        elif self.contour_type == 'Circle':
            center_x, center_y, radius = 3, 3, 2.5
            for angle in np.linspace(0, 360, 16, endpoint=False):
                theta = np.deg2rad(angle)
                x = center_x + radius * np.cos(theta)
                y = center_y + radius * np.sin(theta)
                self.points.append((x, y))
                self.arrows.append(((x, y), (0.2*np.cos(theta), 0.2*np.sin(theta))))
        elif self.contour_type == 'Arc':
            center_x, center_y, radius = 3, 0, 3
            for angle in np.linspace(0, 180, 12):
                theta = np.deg2rad(angle)
                x = center_x + radius * np.cos(theta)
                y = center_y + radius * np.sin(theta)
                self.points.append((x, y))
                self.arrows.append(((x, y), (0, 0.5)))
        self.update_plot()

    def run(self):
        plt.show()


if __name__ == '__main__':
    app = DrillLayoutApp()
    app.run()