使用Hopfield神经网络解决旅行商问题

使用Hopfield神经网络解决旅行商问题(TSP)。这是一种经典的神经网络优化方法。

Hopfield神经网络基础

Hopfield网络是一种递归神经网络,具有能量函数,能够收敛到局部最小值。

classdef HopfieldNetwork < handle
    properties
        num_neurons     % 神经元数量
        weights         % 连接权重矩阵
        biases          % 偏置向量
        state           % 神经元状态
    end
    
    methods
        function obj = HopfieldNetwork(num_neurons)
            obj.num_neurons = num_neurons;
            obj.weights = zeros(num_neurons, num_neurons);
            obj.biases = zeros(num_neurons, 1);
            obj.state = zeros(num_neurons, 1);
        end
        
        function energy = compute_energy(obj)
            % 计算Hopfield网络的能量函数
            energy = -0.5 * obj.state' * obj.weights * obj.state - obj.biases' * obj.state;
        end
        
        function update_neuron(obj, neuron_idx)
            % 更新单个神经元的状态
            input = obj.weights(neuron_idx, :) * obj.state + obj.biases(neuron_idx);
            obj.state(neuron_idx) = 1 / (1 + exp(-input)); % Sigmoid激活函数
        end
        
        function update_network(obj, num_iterations)
            % 更新整个网络
            for iter = 1:num_iterations
                for i = 1:obj.num_neurons
                    obj.update_neuron(i);
                end
                
                % 可选:每100次迭代显示能量
                if mod(iter, 100) == 0
                    energy = obj.compute_energy();
                    fprintf('迭代 %d, 能量: %.4f\n', iter, energy);
                end
            end
        end
    end
end

TSP问题建模与Hopfield网络映射

TSP的Hopfield网络表示

classdef TSPHopfieldSolver < handle
    properties
        num_cities          % 城市数量
        city_positions      % 城市坐标 [N x 2]
        distance_matrix     % 距离矩阵 [N x N]
        
        % Hopfield网络参数
        N                   % 神经元数量 = num_cities × num_cities
        hopfield_net        % Hopfield网络实例
        
        % 能量函数权重系数
        A                   % 行约束权重
        B                   % 列约束权重  
        C                   % 路径长度权重
        D                   % 全局约束权重
    end
    
    methods
        function obj = TSPHopfieldSolver(city_positions, A, B, C, D)
            % 构造函数
            obj.city_positions = city_positions;
            obj.num_cities = size(city_positions, 1);
            obj.N = obj.num_cities ^ 2;
            
            % 设置能量函数权重
            obj.A = A;
            obj.B = B;
            obj.C = C;
            obj.D = D;
            
            % 计算距离矩阵
            obj.distance_matrix = obj.compute_distance_matrix();
            
            % 创建Hopfield网络
            obj.hopfield_net = HopfieldNetwork(obj.N);
            
            % 构建权重矩阵
            obj.build_weight_matrix();
        end
        
        function distances = compute_distance_matrix(obj)
            % 计算城市间的距离矩阵
            distances = zeros(obj.num_cities, obj.num_cities);
            for i = 1:obj.num_cities
                for j = 1:obj.num_cities
                    if i ~= j
                        dist = norm(obj.city_positions(i, :) - obj.city_positions(j, :));
                        distances(i, j) = dist;
                    end
                end
            end
        end
        
        function build_weight_matrix(obj)
            % 构建TSP的Hopfield网络权重矩阵
            obj.hopfield_net.weights = zeros(obj.N, obj.N);
            obj.hopfield_net.biases = zeros(obj.N, 1);
            
            % 四个约束项的权重计算
            for i = 1:obj.num_cities
                for j = 1:obj.num_cities
                    neuron_ij = (i-1) * obj.num_cities + j;
                    
                    for k = 1:obj.num_cities
                        for l = 1:obj.num_cities
                            neuron_kl = (k-1) * obj.num_cities + l;
                            
                            if neuron_ij == neuron_kl
                                continue; % 跳过自连接
                            end
                            
                            % 约束1: 每个城市只能访问一次 (行约束)
                            if i == k && j ~= l
                                obj.hopfield_net.weights(neuron_ij, neuron_kl) = ...
                                    obj.hopfield_net.weights(neuron_ij, neuron_kl) - obj.A;
                            end
                            
                            % 约束2: 每个位置只能有一个城市 (列约束)
                            if j == l && i ~= k
                                obj.hopfield_net.weights(neuron_ij, neuron_kl) = ...
                                    obj.hopfield_net.weights(neuron_ij, neuron_kl) - obj.B;
                            end
                            
                            % 约束3: 总路径长度最小化
                            if j == l-1 || (j == obj.num_cities && l == 1)
                                if i ~= k
                                    dist_ik = obj.distance_matrix(i, k);
                                    obj.hopfield_net.weights(neuron_ij, neuron_kl) = ...
                                        obj.hopfield_net.weights(neuron_ij, neuron_kl) - obj.C * dist_ik;
                                end
                            end
                            
                            % 约束4: 全局激活约束 (确保恰好有N个城市被访问)
                            obj.hopfield_net.weights(neuron_ij, neuron_kl) = ...
                                obj.hopfield_net.weights(neuron_ij, neuron_kl) - obj.D;
                        end
                    end
                    
                    % 偏置项 (全局约束)
                    obj.hopfield_net.biases(neuron_ij) = obj.D * obj.num_cities;
                end
            end
            
            % 确保权重矩阵对称
            obj.hopfield_net.weights = (obj.hopfield_net.weights + obj.hopfield_net.weights') / 2;
        end
        
        function initialize_network(obj, noise_level)
            % 初始化网络状态
            if nargin < 2
                noise_level = 0.1;
            end
            
            % 随机初始化,加入小扰动避免对称性
            base_state = 0.5 * ones(obj.N, 1);
            noise = noise_level * (rand(obj.N, 1) - 0.5);
            obj.hopfield_net.state = base_state + noise;
            
            % 确保状态在[0,1]范围内
            obj.hopfield_net.state = max(0, min(1, obj.hopfield_net.state));
        end
    end
end

网络求解与结果解码

function [best_tour, best_distance, convergence_info] = solve_tsp_hopfield(solver, max_iterations, annealing_schedule)
    % 使用Hopfield网络求解TSP
    % 输入:
    %   solver: TSPHopfieldSolver实例
    %   max_iterations: 最大迭代次数
    %   annealing_schedule: 模拟退火计划 (可选)
    % 输出:
    %   best_tour: 最优路径
    %   best_distance: 最优路径长度
    %   convergence_info: 收敛信息
    
    if nargin < 3
        annealing_schedule = @(iter) 1.0; % 默认无退火
    end
    
    % 初始化网络
    solver.initialize_network();
    
    % 记录收敛信息
    convergence_info.energy = zeros(max_iterations, 1);
    convergence_info.validity = zeros(max_iterations, 1);
    
    best_energy = inf;
    best_state = solver.hopfield_net.state;
    
    for iter = 1:max_iterations
        % 应用模拟退火 (如果提供)
        current_temp = annealing_schedule(iter);
        
        % 更新网络
        old_state = solver.hopfield_net.state;
        
        for i = 1:solver.N
            % 计算输入
            input = solver.hopfield_net.weights(i, :) * solver.hopfield_net.state + ...
                   solver.hopfield_net.biases(i);
            
            % 带温度的sigmoid函数
            solver.hopfield_net.state(i) = 1 / (1 + exp(-input / current_temp));
        end
        
        % 记录能量
        energy = solver.hopfield_net.compute_energy();
        convergence_info.energy(iter) = energy;
        
        % 检查解的有效性
        [is_valid, tour_length] = check_solution_validity(solver);
        convergence_info.validity(iter) = is_valid;
        
        % 更新最优解
        if energy < best_energy && is_valid
            best_energy = energy;
            best_state = solver.hopfield_net.state;
        end
        
        % 显示进度
        if mod(iter, 100) == 0
            fprintf('迭代 %d/%d, 能量: %.4f, 有效解: %d, 路径长度: %.2f\n', ...
                iter, max_iterations, energy, is_valid, tour_length);
        end
        
        % 检查收敛
        if iter > 50 && check_convergence(convergence_info.energy, iter)
            fprintf('在迭代 %d 收敛\n', iter);
            break;
        end
    end
    
    % 恢复最优状态并解码
    solver.hopfield_net.state = best_state;
    [best_tour, best_distance] = decode_solution(solver);
    
    convergence_info.energy = convergence_info.energy(1:iter);
    convergence_info.validity = convergence_info.validity(1:iter);
end

function [is_valid, tour_length] = check_solution_validity(solver)
    % 检查当前网络状态是否表示有效的TSP解
    % 有效解条件: 每行恰好一个1,每列恰好一个1
    
    % 将网络状态重塑为城市×位置的矩阵
    state_matrix = reshape(solver.hopfield_net.state, ...
                          solver.num_cities, solver.num_cities);
    
    % 二值化处理
    binary_matrix = state_matrix > 0.5;
    
    % 检查行约束 (每个城市只访问一次)
    row_sums = sum(binary_matrix, 2);
    row_valid = all(row_sums == 1);
    
    % 检查列约束 (每个位置只有一个城市)
    col_sums = sum(binary_matrix, 1);
    col_valid = all(col_sums == 1);
    
    is_valid = row_valid && col_valid;
    
    % 如果有效,计算路径长度
    if is_valid
        tour = decode_tour_from_matrix(binary_matrix);
        tour_length = compute_tour_length(tour, solver.distance_matrix);
    else
        tour_length = inf;
    end
end

function [tour, distance] = decode_solution(solver)
    % 从网络状态解码TSP路径
    
    state_matrix = reshape(solver.hopfield_net.state, ...
                          solver.num_cities, solver.num_cities);
    
    % 方法1: 直接取最大值
    [~, tour] = max(state_matrix, [], 2);
    
    % 验证tour是否包含所有城市
    if length(unique(tour)) ~= solver.num_cities
        % 方法2: 使用匈牙利算法处理有冲突的情况
        tour = resolve_conflicts(state_matrix);
    end
    
    distance = compute_tour_length(tour, solver.distance_matrix);
end

function tour = resolve_conflicts(state_matrix)
    % 使用类似匈牙利算法的方法解决冲突
    [num_cities, ~] = size(state_matrix);
    
    % 复制状态矩阵
    assignment_matrix = state_matrix;
    tour = zeros(num_cities, 1);
    
    for step = 1:num_cities
        % 找到最大值
        [max_val, max_idx] = max(assignment_matrix(:));
        if max_val <= 0
            break;
        end
        
        [city, position] = ind2sub(size(assignment_matrix), max_idx);
        
        % 分配
        tour(city) = position;
        
        % 清除该行和该列
        assignment_matrix(city, :) = 0;
        assignment_matrix(:, position) = 0;
    end
    
    % 处理未分配的城市
    unassigned = find(tour == 0);
    available_positions = setdiff(1:num_cities, tour(tour > 0));
    
    for i = 1:length(unassigned)
        if i <= length(available_positions)
            tour(unassigned(i)) = available_positions(i);
        else
            % 随机分配剩余位置
            tour(unassigned(i)) = randi(num_cities);
        end
    end
end

function tour_length = compute_tour_length(tour, distance_matrix)
    % 计算路径长度
    num_cities = length(tour);
    tour_length = 0;
    
    for i = 1:num_cities
        from_city = tour(i);
        to_city = tour(mod(i, num_cities) + 1);
        tour_length = tour_length + distance_matrix(from_city, to_city);
    end
end

function converged = check_convergence(energy_history, current_iter)
    % 检查能量是否收敛
    if current_iter < 20
        converged = false;
        return;
    end
    
    window_size = min(10, current_iter);
    recent_energies = energy_history(current_iter-window_size+1:current_iter);
    energy_std = std(recent_energies);
    
    converged = energy_std < 1e-6;
end

完整的TSP求解示例

% 主程序:使用Hopfield网络解决TSP问题
clear; clc;

%% 生成测试数据
rng(42); % 设置随机种子

% 生成随机城市坐标
num_cities = 10;
city_positions = 100 * rand(num_cities, 2);

fprintf('生成 %d 个城市的TSP问题\n', num_cities);

%% 设置Hopfield网络参数
% 能量函数权重系数(需要仔细调整)
A = 500;  % 行约束权重
B = 500;  % 列约束权重
C = 200;  % 路径长度权重  
D = 200;  % 全局约束权重

% 创建TSP求解器
tsp_solver = TSPHopfieldSolver(city_positions, A, B, C, D);

%% 设置模拟退火计划
% 温度衰减函数
cooling_schedule = @(iter) max(0.01, 1.0 * exp(-iter / 500));

%% 求解TSP问题
max_iterations = 2000;
fprintf('开始Hopfield网络优化...\n');

[best_tour, best_distance, convergence_info] = solve_tsp_hopfield(...
    tsp_solver, max_iterations, cooling_schedule);

fprintf('优化完成!\n');
fprintf('最优路径长度: %.2f\n', best_distance);

%% 可视化结果
figure('Position', [100, 100, 1200, 400]);

% 子图1: 城市分布和最优路径
subplot(1, 3, 1);
plot(city_positions(:,1), city_positions(:,2), 'o', 'MarkerSize', 8, ...
     'MarkerFaceColor', 'red', 'MarkerEdgeColor', 'black');
hold on;

% 绘制路径
tour_positions = city_positions(best_tour, :);
tour_positions = [tour_positions; tour_positions(1, :)]; % 回到起点
plot(tour_positions(:,1), tour_positions(:,2), 'b-', 'LineWidth', 2);

% 标注城市编号
for i = 1:num_cities
    text(city_positions(i,1)+2, city_positions(i,2)+2, ...
         sprintf('%d', i), 'FontSize', 10, 'FontWeight', 'bold');
end

title(sprintf('TSP最优路径 (长度: %.2f)', best_distance));
xlabel('X坐标');
ylabel('Y坐标');
grid on;
axis equal;

% 子图2: 能量函数收敛过程
subplot(1, 3, 2);
plot(convergence_info.energy, 'LineWidth', 2);
xlabel('迭代次数');
ylabel('能量函数值');
title('Hopfield网络能量收敛');
grid on;

% 子图3: 解的有效性
subplot(1, 3, 3);
plot(convergence_info.validity, 'LineWidth', 2);
xlabel('迭代次数');
ylabel('解的有效性 (1=有效)');
title('解的有效性演化');
ylim([-0.1, 1.1]);
grid on;

%% 参数敏感性分析
fprintf('\n=== 参数敏感性分析 ===\n');

% 测试不同的权重组合
weight_combinations = [
    500, 500, 200, 200;  % 基准
    800, 800, 100, 100;  % 强约束,弱路径
    200, 200, 500, 500;  % 弱约束,强路径
    600, 600, 300, 300   % 平衡
];

results = cell(size(weight_combinations, 1), 1);

for i = 1:size(weight_combinations, 1)
    weights = weight_combinations(i, :);
    fprintf('测试权重组合 %d: A=%.0f, B=%.0f, C=%.0f, D=%.0f\n', ...
        i, weights(1), weights(2), weights(3), weights(4));
    
    test_solver = TSPHopfieldSolver(city_positions, ...
        weights(1), weights(2), weights(3), weights(4));
    
    [test_tour, test_distance, ~] = solve_tsp_hopfield(...
        test_solver, 1000, cooling_schedule);
    
    results{i} = struct(...
        'weights', weights, ...
        'tour', test_tour, ...
        'distance', test_distance);
    
    fprintf('  路径长度: %.2f\n', test_distance);
end

%% 与传统算法比较
fprintf('\n=== 与最近邻算法比较 ===\n');

% 最近邻算法
nn_tour = nearest_neighbor_tsp(city_positions, tsp_solver.distance_matrix);
nn_distance = compute_tour_length(nn_tour, tsp_solver.distance_matrix);

fprintf('最近邻算法路径长度: %.2f\n', nn_distance);
fprintf('Hopfield网络改进: %.2f%%\n', ...
    (nn_distance - best_distance) / nn_distance * 100);

function tour = nearest_neighbor_tsp(city_positions, distance_matrix)
    % 最近邻算法求解TSP
    num_cities = size(city_positions, 1);
    unvisited = true(num_cities, 1);
    tour = zeros(num_cities, 1);
    
    % 从随机城市开始
    current_city = randi(num_cities);
    tour(1) = current_city;
    unvisited(current_city) = false;
    
    for i = 2:num_cities
        % 找到最近的未访问城市
        distances = distance_matrix(current_city, :);
        distances(~unvisited) = inf;
        
        [~, nearest_city] = min(distances);
        
        tour(i) = nearest_city;
        unvisited(nearest_city) = false;
        current_city = nearest_city;
    end
end

高级改进技术

1. 自适应参数调整

function adaptive_weights = adaptive_weight_adjustment(solver, validity_history)
    % 根据解的有效性自适应调整权重
    
    recent_validity = validity_history(end-min(10, length(validity_history))+1:end);
    validity_rate = mean(recent_validity);
    
    if validity_rate < 0.3
        % 提高约束权重
        adaptive_weights.A = solver.A * 1.2;
        adaptive_weights.B = solver.B * 1.2;
        adaptive_weights.C = solver.C * 0.9;
    elseif validity_rate > 0.8
        % 提高路径优化权重
        adaptive_weights.A = solver.A * 0.9;
        adaptive_weights.B = solver.B * 0.9;
        adaptive_weights.C = solver.C * 1.2;
    else
        adaptive_weights.A = solver.A;
        adaptive_weights.B = solver.B;
        adaptive_weights.C = solver.C;
    end
    adaptive_weights.D = solver.D;
end

2. 多起点优化

function [global_best_tour, global_best_distance] = multi_start_hopfield_tsp(city_positions, num_starts)
    % 多起点Hopfield网络优化
    
    global_best_distance = inf;
    global_best_tour = [];
    
    for start = 1:num_starts
        fprintf('多起点优化: %d/%d\n', start, num_starts);
        
        % 每次使用不同的随机初始化
        solver = TSPHopfieldSolver(city_positions, 500, 500, 200, 200);
        solver.initialize_network(0.2 * start); % 不同的噪声水平
        
        [tour, distance, ~] = solve_tsp_hopfield(solver, 1000);
        
        if distance < global_best_distance
            global_best_distance = distance;
            global_best_tour = tour;
            fprintf('发现更好解: %.2f\n', distance);
        end
    end
end

参考代码 hopfield神经网络解决旅行商问题 www.youwenfan.com/contentcnm/82237.html

关键要点与优化建议

优势:

  1. 并行处理:神经网络天然适合并行计算
  2. 全局搜索:能够跳出局部最优解
  3. 生物启发:基于大脑工作原理的计算模型

挑战与解决方案:

  1. 参数敏感:需要仔细调整权重系数
  2. 收敛性:可能收敛到无效解
  3. 计算复杂度:神经元数量为O(N²)

实用技巧:

  1. 参数调整:通常 A ≈ B > C > D
  2. 模拟退火:结合退火策略提高全局搜索能力
  3. 多起点:多次运行选择最优解
  4. 后处理:对最终解应用2-opt等局部优化

Hopfield神经网络为TSP问题提供了一种独特的解决视角,虽然在实际应用中可能不如专门的组合优化算法高效,但在理论研究和特定场景下仍具有重要价值。

posted @ 2025-11-25 09:39  老夫写代码  阅读(0)  评论(0)    收藏  举报