c++ 模拟退火算法 c++如何实现simulated annealing

老宇吖_3483

老宇吖_3483

2026-03-25

450人浏览

原创

simulated_annealing不发散的关键是合理设初温t0、慢降温、动态内循环次数及约束内嵌邻域;避免nan需用对数空间比较而非直接exp。

c++ 模拟退火算法 c++如何实现simulated annealing

simulated_annealing 函数怎么写才不发散

退火算法跑几十次结果全飘在天边,大概率是温度衰减太猛或初始温度没压住。核心不是堆参数,而是让 accept_probability 在早期真能接受劣解——否则直接退化成贪心。

  • 初始温度 T0 建议用采样法:随机生成 100 个邻域解,取目标函数差值的 95% 分位数绝对值,再除以 log(2)(对应接受概率 ≈ 0.5)
  • 降温策略别硬写 T *= 0.995,改用 T = T0 / log(1 + t)T = T0 / (1 + t * 0.01),慢降比快降更容易跨过局部峰
  • 每次温度下迭代次数不能固定为 10/20,得按当前温度动态设:比如 inner_iters = max(10, static_cast<int>(100 * T / T0))</int>

邻域操作怎么避免越界或非法状态

C++ 里手写邻域一不留神就 std::vector::atout_of_range,或者解向量进了不可行域(比如背包超重、路径重复节点)。关键不是加一堆 if,而是把约束“编译进”邻域生成逻辑里。

  • 对数组索引类变量(如 TSP 路径),邻域用 swapreverse_segment,天然保长度和元素集不变
  • 对浮点决策变量,扰动后立刻用 std::clamp 截断:x = std::clamp(x + delta, low_bound, high_bound)
  • 如果约束复杂(如整数线性约束),宁可每次生成后快速验证,验证失败就重试——比在生成时硬推公式更稳

随机数引擎选 std::mt19937 还是 std::ranlux24

退火依赖高质量随机性,但 std::ranlux24 慢三倍以上,而 std::mt19937 在长序列中可能暴露周期性。实际用法很朴素:

C++ 算法竞赛自动化测试数据生成与校验框架
C++ 算法竞赛自动化测试数据生成与校验框架

根据原题生成新题面、验证器及完整测试数据,自动套用 testlib 模板,用于用户要求生成测试数据时。

下载
  • 全局只建一个 std::mt19937 实例,用 std::random_device{}() 初始化种子,别每次调用都 new 引擎
  • 概率计算统一走 std::uniform_real_distribution<double>(0.0, 1.0)</double>,别用 rand() % 100 / 100.0 —— 低比特周期太短
  • 如果跑多线程退火,每个线程必须有自己的 std::mt19937 实例(种子用 thread_id 混合),否则所有线程输出完全相同

为什么 std::exp((old_cost - new_cost) / T) 经常算出 nan

old_cost - new_cost 是很大的负数(比如 -1000),而 T 已降到 1e-5 级别时,exp(-1e8) 直接下溢成 0,后续除法或比较可能触发未定义行为。这不是数学问题,是浮点精度落地问题。

  • 改用对数空间比较:不计算接受概率,直接生成 u ~ Uniform(0,1),然后判断 log(u)
  • 或者加保护:当 (old_cost - new_cost) / T 时直接拒绝(<code>exp(-700) ≈ 1e-304,double 下限)
  • 别用 std::exp 算小概率,用 std::expm1 或手动泰勒展开前几项反而更糟——退火里不需要那么高精度

退火最麻烦的从来不是公式,而是温度掉到 1e-6 后,double 的有效位数已经不够描述两个相近解的微小差异了。这时候该换数据结构,而不是调参数。

C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!

相关文章

c++速学教程(入门到精通)
c++速学教程(入门到精通)

c++怎么学习?c++怎么入门?c++在哪学?c++怎么学才快?不用担心,这里为大家提供了c++速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

c++

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

2025.08.29

3188

10

C++中int、float和double的区别
C++中int、float和double的区别

本专题整合了c++中int和double的区别,阅读专题下面的文章了解更多详细内容。

2025.10.23

584

4

treenode的用法
treenode的用法

​在计算机编程领域,TreeNode是一种常见的数据结构,通常用于构建树形结构。在不同的编程语言中,TreeNode可能有不同的实现方式和用法,通常用于表示树的节点信息。更多关于treenode相关问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.12.01

2121

7

C++ 高效算法与数据结构
C++ 高效算法与数据结构

本专题讲解 C++ 中常用算法与数据结构的实现与优化,涵盖排序算法(快速排序、归并排序)、查找算法、图算法、动态规划、贪心算法等,并结合实际案例分析如何选择最优算法来提高程序效率。通过深入理解数据结构(链表、树、堆、哈希表等),帮助开发者提升 在复杂应用中的算法设计与性能优化能力。

2025.12.22

296

20

深入理解算法:高效算法与数据结构专题
深入理解算法:高效算法与数据结构专题

本专题专注于算法与数据结构的核心概念,适合想深入理解并提升编程能力的开发者。专题内容包括常见数据结构的实现与应用,如数组、链表、栈、队列、哈希表、树、图等;以及高效的排序算法、搜索算法、动态规划等经典算法。通过详细的讲解与复杂度分析,帮助开发者不仅能熟练运用这些基础知识,还能在实际编程中优化性能,提高代码的执行效率。本专题适合准备面试的开发者,也适合希望提高算法思维的编程爱好者。

2026.01.06

337

22

C++ 数据结构与算法实现教程合集
C++ 数据结构与算法实现教程合集

以 C++ 为实现语言,系统讲解核心数据结构与算法,涵盖链表(单链表/双链表/环检测)、栈与队列(单调栈/优先队列)、二叉树(遍历/BST/AVL/红黑树)、哈希表(开地址法/链地址法)、图(邻接表/BFS/DFS/Dijkstra/拓扑排序)、常见排序算法(快排/归并/堆排/计数排序)的实现与复杂度分析,同时分享 LeetCode 刷题技巧、竞赛编程常用模板(二分/前缀和/滑动窗口/动态规划),帮助开发者夯实算法基础。

2026.05.09

372

25

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

2023.07.18

4547

5

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

2023.08.10

2088

6

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

2023.08.10

3478

6

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Conan 2 Essentials 免费课程
Conan 2 Essentials 免费课程

共0课时 | 0人学习

CMake 与 Conan 集成实践
CMake 与 Conan 集成实践

共0课时 | 0人学习

Conan 2 高级依赖模型介绍
Conan 2 高级依赖模型介绍

共0课时 | 0人学习