【opencv】示例-travelsalesman.cpp 使用模拟退火算法求解旅行商问题

0446b2afe218c87af03978969e6983bd.png

6eb23516b6dbfac595d1d35f62b8b3ee.png

3f6ce269db2eaaf6bfd4d672d76e98e1.png

// 载入 OpenCV 的核心头文件
#include <opencv2/core.hpp>
// 载入 OpenCV 的图像处理头文件
#include <opencv2/imgproc.hpp>
// 载入 OpenCV 的高层GUI(图形用户界面)头文件
#include <opencv2/highgui.hpp>
// 载入 OpenCV 的机器学习模块头文件
#include <opencv2/ml.hpp>


// 使用命名空间cv,避免每次调用 OpenCV 的功能时都要前缀cv::
using namespace cv;


// 定义旅行商(TravelSalesman)类
class TravelSalesman
{
private :
    // 私有成员:城市位置向量的引用
    const std::vector<Point>& posCity;
    // 私有成员:下一个城市索引的向量引用
    std::vector<int>& next;
    // 私有成员:随机数生成器
    RNG rng;
    // 私有成员:用于记录状态改变的城市索引
    int d0,d1,d2,d3;


public:
    // 构造函数初始化城市位置和下一个城市的索引
    TravelSalesman(std::vector<Point> &p, std::vector<int> &n) :
        posCity(p), next(n)
    {
        // 初始化随机数生成器
        rng = theRNG();
    }
    // 返回系统状态的能量值
    double energy() const;
    // 改变系统状态(随机扰动)
    void changeState();
    // 撤销到之前的状态
    void reverseState();


};


// 实现改变状态的函数
void TravelSalesman::changeState()
{
    // 产生随机城市索引
    d0 = rng.uniform(0,static_cast<int>(posCity.size()));
    // 获取随机城市后的各个城市索引
    d1 = next[d0];
    d2 = next[d1];
    d3 = next[d2];


    // 更改城市访问的顺序
    next[d0] = d2;
    next[d2] = d1;
    next[d1] = d3;
}


// 实现撤销状态改变的函数
void TravelSalesman::reverseState()
{
    // 恢复原来的城市访问顺序
    next[d0] = d1;
    next[d1] = d2;
    next[d2] = d3;
}


// 实现计算能量值的函数,能量值为城市间距离的总和
double TravelSalesman::energy() const
{
    // 初始化能量值
    double e = 0;
    // 遍历城市计算总距离
    for (size_t i = 0; i < next.size(); i++)
    {
        // 计算两城市间距离并累加到能量值
        e += norm(posCity[i]-posCity[next[i]]);
    }
    // 返回总能量值
    return e;
}


// 绘制每个城市点和城市间连线
static void DrawTravelMap(Mat &img, std::vector<Point> &p, std::vector<int> &n)
{
    // 遍历所有城市
    for (size_t i = 0; i < n.size(); i++)
    {
        // 在图像中用小圆点表示城市位置
        circle(img,p[i],5,Scalar(0,0,255),2);
        // 连接城市间的线表示旅行路径
        line(img,p[i],p[n[i]],Scalar(0,255,0),2);
    }
}


int main(void)
{
    // 设置城市数量
    int nbCity=40;
    // 创建图像,用于显示城市地图
    Mat img(500,500,CV_8UC3,Scalar::all(0));
    // 初始化随机数生成器,种子为123456
    RNG rng(123456);
    // 设置城市生成的半径范围
    int radius=static_cast<int>(img.cols*0.45);
    // 设置图像中心点位置
    Point center(img.cols/2,img.rows/2);


    // 初始化城市位置向量和下一个城市索引向量
    std::vector<Point> posCity(nbCity);
    std::vector<int> next(nbCity);
    // 随机生成城市位置
    for (size_t i = 0; i < posCity.size(); i++)
    {
        // 在圆周上均匀分布城市
        double theta = rng.uniform(0., 2 * CV_PI);
        // 计算城市的坐标并存储
        posCity[i].x = static_cast<int>(radius*cos(theta)) + center.x;
        posCity[i].y = static_cast<int>(radius*sin(theta)) + center.y;
        // 设定下一个城市的索引
        next[i]=(i+1)%nbCity;
    }
    // 创建旅行商问题系统实例
    TravelSalesman ts_system(posCity, next);


    // 绘制初始的旅行商问题地图
    DrawTravelMap(img,posCity,next);
    // 显示地图窗口
    imshow("Map",img);
    // 短暂等待时间
    waitKey(10);
    // 初始化模拟退火算法的当前温度
    double currentTemperature = 100.0;
    // 模拟退火循环,直到连续10次没有改变发生时停止
    for (int i = 0, zeroChanges = 0; zeroChanges < 10; i++)
    {
        // 执行模拟退火算法,尝试改变系统状态
        int changesApplied = ml::simulatedAnnealingSolver(ts_system, currentTemperature, currentTemperature*0.97, 0.99, 10000*nbCity, &currentTemperature, rng);
        // 重绘图像,显示新的旅行路径
        img.setTo(Scalar::all(0));
        DrawTravelMap(img, posCity, next);
        imshow("Map", img);
        // 短暂等待时间并检查是否有退出键被按下
        int k = waitKey(10);
        // 输出当前循环的信息
        std::cout << "i=" << i << " changesApplied=" << changesApplied << " temp=" << currentTemperature << " result=" << ts_system.energy() << std::endl;
        // 如果用户按下退出键,则退出程序
        if (k == 27 || k == 'q' || k == 'Q')
            return 0;
        // 如果没有改变发生,则计数器加1
        if (changesApplied == 0)
            zeroChanges++;
    }
    // 完成模拟退火算法,输出结束信息
    std::cout << "Done" << std::endl;
    // 等待用户按键以退出
    waitKey(0);
    // 程序结束
    return 0;
}

这段代码实现了一个使用模拟退火算法的旅行商问题解决方案。在这个解决方案中,首先随机在一个圆周上生成一定数量的城市,并在地图上用圆点和连线显示出旅行商访问城市的路径。然后,通过模拟退火算法不断尝试随机扰动城市访问的顺序,通过最小化城市间路径的总长度来寻找最优解(即最短路径)。代码中绘图部分使用了OpenCV库,而模拟退火的具体实现使用了OpenCV的机器学习模块。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/544264.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数据库:SQL分类之DQL详解

1.DQL语法 select 字段列表 from 表名列表 where 条件列表 group by 分组字段列表 having 分组后条件列表 order by 排序字段列表 limit 分页参数 基本查询 条件查询&#xff08;where&#xff09; 聚合函数&#xff08;count、max、min、avg、sum &#xff09; 分组查询&…

Linux网络基础 (二) ——(IP、MAC、端口号、TCPUDP协议、网络字节序)

文章目录 IP 地址基本概念源IP地址 & 目的IP地址 MAC 地址基本概念源MAC地址 & 目的MAC地址 端口号基本概念源端口号 & 目的端口号 TCP & UDP 协议基本概念TCP 与 UDP 的抉择 网络字节序大端、小端字节序 &#x1f396; 博主的CSDN主页&#xff1a;Ryan.Alask…

OLTP 与 OLAP 系统说明对比和大数据经典架构 Lambda 和 Kappa 说明对比——解读大数据架构(五)

文章目录 前言OLTP 和 OLAPSMP 和 MPPlambda 架构Kappa 架构 前言 本文我们将研究不同类型的大数据架构设计&#xff0c;将讨论 OLTP 和 OLAP 的系统设计&#xff0c;以及有效处理数据的策略包括 SMP 和 MPP 等概念。然后我们将了解经典的 Lambda 架构和 Kappa 架构。 OLTP …

杰发科技AC7840——CAN通信简介(5)_可变波特率设置

0. 简介 设置可变波特率时候&#xff0c;遇到2个坑&#xff0c;在此记录下来 使用该函数即可 can_time_segment_t bitrate2 s_canBitrate[CAN_BITRATE_250K]; CAN_DRV_SetBitrate(instance, &bitrate2); 1. 波特率指针注意不要空 查看设置波特率的接口&#xff0c;发现…

Pytest精通指南(09)利用Fixture给函数设置别名

文章目录 前言测试用例默认显示传递一个参数传递多个参数 利用Fixture修改测试函数名称传递一个参数传递多个参数 验证ids和params长度不一致修改Fixture函数名称 前言 在 pytest 中&#xff0c;pytest.fixture 装饰器用于定义可以在多个测试函数中重用的设置和清理代码。 name…

C/C++基础----内存相关

malloc分配内存 用法 参数为要开辟内存的大小&#xff08;字节为单位&#xff09;返回值为void*,所以要强转一下语法&#xff1a;malloc()动态开辟20个字节的内存&#xff0c;代码&#xff1a;#include <iostream>using namespace std;int main() {int *a (int *) mal…

安全加速SCDN带的态势感知能为网站安全带来哪些帮助

随着安全加速SCDN被越来越多的用户使用&#xff0c;很多用户都不知道安全加速SCDN的态势感知是用于做什么的&#xff0c;德迅云安全今天就带大家来了解下什么是态势感知&#xff0c;态势感知顾名思义就是对未发生的事件进行预知&#xff0c;并提前进行防范措施的布置&#xff0…

内网渗透-Earthworm的简单使用(内网穿透工具)

Earthworm的简单介绍&#xff08;一&#xff09; 文章目录 EarthWorm下载地址1. 普通网络 1.1 跳板机存在公网IP 1.1.1 网络环境1.1.2 使用方法1.1.3 流量走向 1.2 跳板机不存在公网IP&#xff0c;可出网 1.2.1 网络环境1.2.2 使用方法1.2.3 流量走向 2. 二级网络 2.1 一级跳…

系统架构最佳实践 -- 金融企业的资损问题介绍

什么是资损 资损通常来讲是指支付场景下的资金损失&#xff0c;这里可以从两个维度看 用户角度&#xff1a;多扣用户款导致用户资金损失&#xff0c;此问题一般需要通过客服等渠道反馈&#xff0c;可以把多的钱退给用户&#xff0c;但是很大程度上损失了用户体验&#xff1b; …

ESP32 S3音频开发

1. 音频硬件框架 Codec&#xff1a;音频编解码芯片&#xff0c;一种低功耗单声道音频编解码器&#xff0c;包含单通道 ADC、单通道 DAC、低噪声前置放大器、耳机驱动器、数字音效、模拟混音和增益功能。它通过 I2S 和 I2C 总线与 ESP32-S3-WROOM-1 模组连接&#xff0c;以提供独…

计算机视觉实验五——图像分割

计算机视觉实验五——图像分割 一、实验目标二、实验内容1.了解图割操作&#xff0c;实现用户交互式分割&#xff0c;通过在一幅图像上为前景和背景提供一些标记或利用边界框选择一个包含前景的区域&#xff0c;实现分割①图片准备②代码③运行结果④代码说明 2.采用聚类法实现…

64B/66B GT Transceiver 配置

一、前言 前一篇文章已经讲述了64B/66B的编码原理&#xff0c;此篇文章来配置一下7系列GT的64B/66B编码。并讲述所对应的例子工程的架构&#xff0c;以及部分代码的含义。 二、IP核配置 1、打开7 Series FPGAs Transceiver Wizards&#xff0c;选择将共享逻辑放置在example …

全局代理导致JetBrains IDE CPU占用高,jdk.internal.net.http.common

GoLand版本&#xff1a;2022.3.4 解决办法&#xff1a; 使用SOCKS代理代替HTTP代理 禁用Space和Code With Me插件 禁用 TLS V1.3&#xff0c;参考&#xff1a;https://stackoverflow.com/questions/54485755/java-11-httpclient-leads-to-endless-ssl-loop 参考 https://…

强大的压缩和解压缩工具 Keka for Mac

Keka for Mac是一款功能强大的压缩和解压缩工具&#xff0c;专为Mac用户设计。它支持多种压缩格式&#xff0c;包括7z、Zip、Tar、Gzip和Bzip2等&#xff0c;无论是发送电子邮件、备份文件还是节省磁盘空间&#xff0c;Keka都能轻松满足用户需求。 这款软件的操作简单直观&…

【OpenHarmony】XTS环境配置

零、参考 1、xts测试环境配置&#xff1a;https://www.yuque.com/u25440504/ehvzki/ik2fso 2、Windows安装Python、pip、easy_install的方法&#xff1a;https://pythonjishu.com/bmxqeisbkzgrpnn/ 3、Python中easy_install 和 pip 的安装及使用&#xff1a; https://blog.c…

C语言之offsetof实现分析(九十一)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

做一个后台项目的架构

后台架构的11个维度 架构1&#xff1a;团队协助基础工具链的选型和培训架构2&#xff1a;搭建微服务开发基础设施架构3&#xff1a;选择合适的RPC框架架构4&#xff1a;选择和搭建高可用的注册中心架构5&#xff1a;选择和搭建高可用的配置中心架构6&#xff1a;选择和搭建高性…

React 19 的新增功能:Action Hooks

React 是前端开发领域最流行的框架之一。我喜欢 React 是因为它背后的团队和社区对它的热情。当社区提出新功能和改进的需求时&#xff0c;团队会倾听&#xff0c;React 的未来是令人兴奋和有趣的。 让我们来看一下 React 19 中令开发人员提升开发效率的新特性。对于每个钩子&…

STL--list双向链表

功能 将数据进行链式存储 链表&#xff08;list&#xff09;是一种物理存储单元上非连续的存储结构&#xff0c;数据元素的逻辑顺序是通过链表中的指针链接实现的 链表的组成&#xff1a;链表由一系列结点组成 结点的组成&#xff1a;一个是存储数据元素的数据域&#xff0…

FJSP:袋鼠群优化(Kangaroo Swarm Optimization ,KSO)算法求解柔性作业车间调度问题(FJSP),提供MATLAB代码

一、柔性作业车间调度问题 柔性作业车间调度问题&#xff08;Flexible Job Shop Scheduling Problem&#xff0c;FJSP&#xff09;&#xff0c;是一种经典的组合优化问题。在FJSP问题中&#xff0c;有多个作业需要在多个机器上进行加工&#xff0c;每个作业由一系列工序组成&a…