找回密码
 立即注册
首页 业界区 业界 模拟退火算法

模拟退火算法

旁拮猾 1 小时前
模拟退火算法

​    模拟退火算法最早的思想由Metropolis 等( 1953 )提出, 1983 Kirkpatrick 等将其应用于组合优化。
算法的目的
克服优化过程陷入局部极小;
克服初值依赖性。
物理退火过程

在物理学中,退火是将金属加热到极高温度,然后让其极其缓慢地冷却的过程。

  • 高温状态:原子运动剧烈,处于无序状态(高能量)。
  • 等温过程  对于与环境换热而温度不变的封闭系统,系统状态的自发变化总是朝自由能减少的方向进行,当自由能达到最小时,系统达到平衡态;
  • 缓慢冷却:原子逐渐找到最稳定的位置,形成整齐的晶体结构。
  • 最终状态:系统的内能最低(全局最优)。
如果冷却得太快(淬火,Quenching),原子来不及调整位置就被“冻结”在杂乱的状态,系统处于亚稳态(局部最优,内能较高,材料脆)。
温度越低,物体的能量状态越低,到达足够的低点时,液体开始冷凝与结晶,在结晶状态时,系统的能量状态最低。缓慢降温(退火时,可达到最低能量状态;但如果快速降温(淬火,会导致不是最低能态的非晶形。
Boltzmann概率分布

在温度T,分子停留在状态r满足Boltzmann概率分布
1.png

2.webp


在同一个温度T,选定两个能量E1    auto solve(            const State& initial_state,            EnergyFunc energy_func,            Params params = Params{},            NeighborFunc neighbor = NeighborFunc{},            CoolingPolicy cooling = CoolingPolicy{},            ConstraintPolicy constraint = ConstraintPolicy{}    ) {        using AcceptancePolicy = MetropolisAcceptance;        detail::Solver                solver(params, energy_func, neighbor, cooling, AcceptancePolicy{}, constraint);        return solver.solve(initial_state);    }} // namespace sa#endif // SA_SA_HPP[/code]policies.hpp
  1. #ifndef SA_SA_HPP
  2. #define SA_SA_HPP
  3. #include "params.hpp"
  4. #include "policies.hpp"
  5. #include "detail/solver.hpp"
  6. namespace sa {
  7.     /**
  8.      * @brief 模拟退火通用求解函数
  9.      * * @tparam State 状态类型 (自动推导)
  10.      * @tparam EnergyFunc 能量函数类型 (自动推导)
  11.      * @tparam NeighborFunc 邻域函数类型 (可选)
  12.      * @tparam CoolingPolicy 降温策略 (可选)
  13.      * @tparam ConstraintPolicy 约束策略 (可选)
  14.      * * @param initial_state 初始状态值
  15.      * @param energy_func 能量函数句柄
  16.      * @param params 算法参数配置
  17.      * @param neighbor 邻域生成器实例
  18.      * @param cooling 降温器实例
  19.      * @param constraint 约束器实例
  20.      * @return std::pair<State, double> {最优状态, 最优能量值}
  21.      */
  22.     template<
  23.             typename State,
  24.             typename EnergyFunc,
  25.             typename NeighborFunc = DefaultNeighbor<State>,
  26.             typename CoolingPolicy = ExponentialCooling,
  27.             typename ConstraintPolicy = std::nullptr_t
  28.     >
  29.     auto solve(
  30.             const State& initial_state,
  31.             EnergyFunc energy_func,
  32.             Params params = Params{},
  33.             NeighborFunc neighbor = NeighborFunc{},
  34.             CoolingPolicy cooling = CoolingPolicy{},
  35.             ConstraintPolicy constraint = ConstraintPolicy{}
  36.     ) {
  37.         using AcceptancePolicy = MetropolisAcceptance;
  38.         detail::Solver<State, EnergyFunc, NeighborFunc, CoolingPolicy, AcceptancePolicy, ConstraintPolicy>
  39.                 solver(params, energy_func, neighbor, cooling, AcceptancePolicy{}, constraint);
  40.         return solver.solve(initial_state);
  41.     }
  42. } // namespace sa
  43. #endif // SA_SA_HPP
复制代码
params.hpp
  1. #ifndef SA_POLICIES_HPP
  2. #define SA_POLICIES_HPP
  3. #include "params.hpp"
  4. #include "detail/traits.hpp"
  5. #include <cmath>
  6. #include <random>
  7. #include
  8. #include <stdexcept>
  9. #include <vector>
  10. namespace sa {
  11.     // 默认降温策略
  12.     struct ExponentialCooling {
  13.         inline double operator()(double T, const Params& p) const noexcept {
  14.             return T * p.alpha;
  15.         }
  16.     };
  17.     // 默认接受策略 (Metropolis 准则)
  18.     struct MetropolisAcceptance {
  19.         template<typename RNG>
  20.         bool operator()(double delta_E,
  21.                         double T,
  22.                         RNG& rng,
  23.                         std::uniform_real_distribution<double>& dist) const
  24.         {
  25.             if (delta_E < 0.0) return true;
  26.             return std::exp(-delta_E / T) > dist(rng);
  27.         }
  28.     };
  29.     // 默认连续邻域生成策略
  30.     template<typename State>
  31.     struct DefaultNeighbor {
  32.         double sigma = 1.0;
  33.         State operator()(const State& current,
  34.                          double T,
  35.                          std::mt19937& rng) const
  36.         {
  37.             if constexpr (std::is_arithmetic_v<State>) {
  38.                 std::normal_distribution<double> dist(0.0, sigma * T);
  39.                 return static_cast<State>(current + dist(rng));
  40.             }
  41.             else if constexpr (detail::is_std_vector_v<State>) {
  42.                 using ValueType = typename State::value_type;
  43.                 static_assert(std::is_arithmetic_v<ValueType>,
  44.                               "vector value type must be arithmetic");
  45.                 std::normal_distribution<double> dist(0.0, sigma * T);
  46.                 State candidate = current;
  47.                 for (auto& v : candidate)
  48.                     v = static_cast<ValueType>(v + dist(rng));
  49.                 return candidate;
  50.             }
  51.             else {
  52.                 static_assert(sizeof(State) == 0, "No default neighbor for this State type");
  53.                 return current;
  54.             }
  55.         }
  56.     };
  57.     // 离散翻转邻域策略 (针对 vector<bool> 或 vector<int>)
  58.     template<typename State>
  59.     struct DiscreteFlipNeighbor {
  60.         State operator()(const State& current,
  61.                          double T,
  62.                          std::mt19937& rng) const
  63.         {
  64.             static_assert(detail::is_std_vector_v<State>, "DiscreteFlipNeighbor requires std::vector");
  65.             using ValueType = typename State::value_type;
  66.             static_assert(
  67.                     std::is_same_v<ValueType, int> || std::is_same_v<ValueType, bool>,
  68.                     "DiscreteFlipNeighbor requires vector<int> or vector<bool>"
  69.             );
  70.             State candidate = current;
  71.             std::uniform_int_distribution<std::size_t> dist(0, candidate.size() - 1);
  72.             std::size_t idx = dist(rng);
  73.             if constexpr (std::is_same_v<ValueType, bool>)
  74.                 candidate[idx] = !candidate[idx];
  75.             else
  76.                 candidate[idx] = 1 - candidate[idx];
  77.             return candidate;
  78.         }
  79.     };
  80.     // 边界约束策略 (Box Constraint)
  81.     template<typename State>
  82.     class BoxConstraintPolicy {
  83.     public:
  84.         using ValueType = std::conditional_t<
  85.                 std::is_arithmetic_v<State>,
  86.                 State,
  87.                 typename State::value_type>;
  88.         BoxConstraintPolicy(ValueType lower, ValueType upper)
  89.                 : lower_(lower), upper_(upper) {}
  90.         void apply(State& state) const noexcept {
  91.             if constexpr (std::is_arithmetic_v<State>) {
  92.                 state = std::clamp(state, lower_, upper_);
  93.             }
  94.             else {
  95.                 for (auto& v : state)
  96.                     v = std::clamp(v, lower_, upper_);
  97.             }
  98.         }
  99.     private:
  100.         ValueType lower_;
  101.         ValueType upper_;
  102.     };
  103. } // namespace sa
  104. #endif // SA_POLICIES_HPP
复制代码
solver.hpp
[code]#ifndef SA_DETAIL_SOLVER_HPP#define SA_DETAIL_SOLVER_HPP#include "../params.hpp"#include #include #include namespace sa::detail {    template<            typename State,            typename EnergyFunc,            typename NeighborFunc,            typename CoolingPolicy,            typename AcceptancePolicy,            typename ConstraintPolicy    >    class Solver {    public:        Solver(Params params,               EnergyFunc energy,               NeighborFunc neighbor,               CoolingPolicy cooling,               AcceptancePolicy acceptance,               ConstraintPolicy constraint)                : params_(params),                  energy_(energy),                  neighbor_(neighbor),                  cooling_(cooling),                  acceptance_(acceptance),                  constraint_(constraint),                  dist_(0.0, 1.0)        {            validate_params();            if (params_.seed == 0) {                std::random_device rd;                rng_ = std::mt19937(rd());            } else {                rng_ = std::mt19937(params_.seed);            }        }        std::pair solve(const State& initial_state) {            State current = initial_state;            double current_energy = energy_(current);            State best = current;            double best_energy = current_energy;            double T = params_.initial_temp;            std::size_t total_iters = 0;            while (T > params_.final_temp && total_iters < params_.max_total_iters) {                for (std::size_t i = 0;                     i < params_.iter_per_temp && total_iters < params_.max_total_iters;                     ++i, ++total_iters)                {                    State candidate = neighbor_(current, T, rng_);                    // 编译期判断是否存在约束策略                    if constexpr (!std::is_same_v) {                        constraint_.apply(candidate);                    }                    double candidate_energy = energy_(candidate);                    double delta = candidate_energy - current_energy;                    if (acceptance_(delta, T, rng_, dist_)) {                        current = std::move(candidate);                        current_energy = candidate_energy;                        if (current_energy < best_energy) {                            best = current;                            best_energy = current_energy;                        }                    }                }                T = cooling_(T, params_);            }            return {std::move(best), best_energy};        }    private:        void validate_params() {            if (params_.initial_temp

相关推荐

您需要登录后才可以回帖 登录 | 立即注册