线性方程约束下修正方法的可行性分析(程序设计)

前言

    博客 《线性方程约束下修正方法的可行性分析(演绎推理,上)》《线性方程约束下修正方法的可行性分析(演绎推理,中)》《线性方程约束下修正方法的可行性分析(演绎推理,下)》通过严格的演绎推理得到了线性方程约束下修正方法可行性的一般性判别方法,特别是给出了多线性方程约束下通过博客《一种线性方程约束下生成随机数修正的一般性方法(上)》《一种线性方程约束下生成随机数修正的一般性方法(下)》所提修正方法得到的修正结果的可行性分析。上述方法在求解一般线性方程约束问题时展现出了普适性、理论性和准确性,然而在实际的工程求解当中也会暴露出计算公式复杂、求解程序设计困难等问题。为解决以上不足,本博客将对通过演绎推理得到的修正结果可行性分析方法尤其是多线性方程约束下的修正结果可行性分析方法进行适当简化,以方便将可行性分析程序移植到通过各类编程软件编写的程序当中,在保证可行性分析方法准确性的前提下,提升可行性分析方法的可移植性。

程序设计框架

生成随机数的循环修正

Created with Raphaël 2.3.0 开始 生成随机数x_gen run = 0 run = run + 1 将生成随机数x_gen修正为x_cor 修正结果x_cor可行? 修正随机数x_cor 结束 run >= max_runtime? x_gen = x_cor yes no yes no

MATLAB程序代码

生成随机数的循环修正程序

while 1
    
    ...

    run = run + 1;
    % Feasible
    if all(correction_info.is_feasible)
        break;
    end
    % Infeasible
    % Variable max_runtime is specified as 10 by default
    if ~any(correction_info.is_feasible) && run > max_runtime
        x_cor = [];
        correction_info.is_feasible = false(1, N_P);
        correction_info.does_x_cor_exceed.by_bit = true(N_D, N_P);
        correction_info.does_x_cor_exceed.globally = true(1, N_P);
        correction_info.is_equation_equal_to_b.by_bit = false(M, N_P);
        correction_info.is_equation_equal_to_b.globally = false;
        break;
    end

    % Update x_gen
    x_gen = x_cor;
end

linear_equations_constraints_correction函数

function [x_cor, correction_info] = linear_equations_constraints_correction(x_gen, lb, ub, A_eq, b_eq, ...
                                    max_runtime)
    % LINEAR_EQUATIONS_CONSTRAINTS_CORRECTION  Correction onto generated random vector.
    %                                          A methodology of correction onto generated random vector,
    %                                          facilitating the corrected vector to range within variable
    %                                          boundaries and to meet linear constraints

    if ~exist('max_runtime', 'var')
        max_runtime = 10;
    end
    
    Ab_eq = [A_eq, b_eq];
    
    M = size(A_eq, 1);
    [N_D, N_P] = size(x_gen);

    % Invoke Python for an accurate computation of the reduced row echelon form of Ab_eq
    Ab_eq_py = py.numpy.array(Ab_eq);
    Ab_eq_RREF_sym = py.sympy.Matrix(Ab_eq_py).rref();
    Ab_eq_RREF_raw = double(py.numpy.asarray(Ab_eq_RREF_sym(1), dtype = 'float'));
    if size(Ab_eq, 1) == 1
        Ab_eq_RREF = Ab_eq_RREF_raw;
    else
        Ab_eq_RREF = reshape(Ab_eq_RREF_raw, size(Ab_eq_RREF_raw, 2), size(Ab_eq_RREF_raw, 3));
    end

    R_A = sum(any(Ab_eq_RREF(:, 1:end - 1), 2), 1);
    R_Ab = sum(any(Ab_eq_RREF, 2), 1);
    
    if R_A < R_Ab
        x_cor = [];
        correction_info.is_feasible = false(1, N_P);
        correction_info.does_x_cor_exceed.by_bit = true(N_D, N_P);
        correction_info.does_x_cor_exceed.globally = true(1, N_P);
        correction_info.is_equation_equal_to_b.by_bit = false(M, N_P);
        correction_info.is_equation_equal_to_b.globally = false;
    
    else
        if R_A == N_D
            x_cor = Ab_eq_RREF(1:N_D, end);
    
        else
            x_cor = x_gen;

            if R_A == 1
                A_eq_candi = A_eq(1, :);
                Eq_gen = A_eq_candi * x_gen;

                b_eq_candi_lb = A_eq_candi * ((A_eq_candi > 0)' .* lb + (A_eq_candi < 0)' .* ub);
                b_eq_candi_ub = A_eq_candi * ((A_eq_candi > 0)' .* ub + (A_eq_candi < 0)' .* lb);
                delta_plus = A_eq_candi * ((A_eq_candi > 0)' .* (x_gen - lb) + (A_eq_candi < 0)' .* (x_gen - ub));
                delta_minus = A_eq_candi * ((A_eq_candi > 0)' .* (x_gen - ub) + (A_eq_candi < 0)' .* (x_gen - lb));

                for indi = 1:N_P
                    if Eq_gen(:, indi) > b_eq
                        x_cor(A_eq_candi > 0, indi) = (((b_eq - b_eq_candi_lb) / delta_plus(indi)) * (x_gen(A_eq_candi > 0, indi) - lb(A_eq_candi > 0)) ...
                                                      + lb(A_eq_candi > 0))';
                        x_cor(A_eq_candi == 0, indi) = (x_gen(A_eq_candi == 0, indi))';
                        x_cor(A_eq_candi < 0, indi) = (((b_eq - b_eq_candi_lb) / delta_plus(indi)) * (x_gen(A_eq_candi < 0, indi) - ub(A_eq_candi < 0)) ...
                                                      + ub(A_eq_candi < 0))';
                    elseif Eq_gen(:, indi) < b_eq
                        x_cor(A_eq_candi > 0, indi) = (((b_eq - b_eq_candi_ub) / delta_minus(indi)) * (x_gen(A_eq_candi > 0, indi) - ub(A_eq_candi > 0)) ...
                                                      + ub(A_eq_candi > 0))';
                        x_cor(A_eq_candi == 0, indi) = (x_gen(A_eq_candi == 0, indi))';
                        x_cor(A_eq_candi < 0, indi) = (((b_eq - b_eq_candi_ub) / delta_minus(indi)) * (x_gen(A_eq_candi < 0, indi) - lb(A_eq_candi < 0)) ...
                                                      + lb(A_eq_candi < 0))';
                    end
                end

            else
                lb_base = lb(R_A + 1:end, :);
                ub_base = ub(R_A + 1:end, :);
                A_eq_tilde = Ab_eq_RREF(1:R_A, R_A + 1:end - 1);
                b_eq_tilde_lb = diag(A_eq_tilde * ((A_eq_tilde > 0)' .* lb_base + (A_eq_tilde < 0)' .* ub_base));
                b_eq_tilde_ub = diag(A_eq_tilde * ((A_eq_tilde > 0)' .* ub_base + (A_eq_tilde < 0)' .* lb_base));
                b_eq_tilde_min = Ab_eq_RREF(:, end) - ub(1:R_A, end);
                b_eq_tilde_max = Ab_eq_RREF(:, end) - lb(1:R_A, end);
                
                if any(b_eq_tilde_max < b_eq_tilde_lb) || any(b_eq_tilde_min > b_eq_tilde_ub)
                    x_cor = [];
                    correction_info.is_feasible = false(1, N_P);
                    correction_info.does_x_cor_exceed.by_bit = true(N_D, N_P);
                    correction_info.does_x_cor_exceed.globally = true(1, N_P);
                    correction_info.is_equation_equal_to_b.by_bit = false(M, N_P);
                    correction_info.is_equation_equal_to_b.globally = false;
                else
                    run = 0;
                    while 1
                        x_cor = x_gen;
                        x_gen_base = x_gen(R_A + 1:end, :);
                        Eq_tilde_gen = A_eq_tilde * x_gen_base;
                        does_A_eq_tilde_x_gen_base_exceed = (Eq_tilde_gen < b_eq_tilde_min) ...
                                                            | (Eq_tilde_gen > b_eq_tilde_max);

                        for indi = 1:N_P
                            if any(does_A_eq_tilde_x_gen_base_exceed(:, indi))
                                flag_A_eq_tilde_x_gen_base_exceed = find(does_A_eq_tilde_x_gen_base_exceed(:, indi));
                                row_A_eq_tilde_candi = flag_A_eq_tilde_x_gen_base_exceed(randi(length(flag_A_eq_tilde_x_gen_base_exceed)));
                                A_eq_tilde_candi = A_eq_tilde(row_A_eq_tilde_candi, :);
                                Eq_tilde_candi_gen = A_eq_tilde_candi * x_gen_base(:, indi);
                                b_eq_k_tilde_lb = A_eq_tilde_candi * ((A_eq_tilde_candi > 0)' .* lb_base ...
                                                  + (A_eq_tilde_candi < 0)' .* ub_base);
                                b_eq_k_tilde_ub = A_eq_tilde_candi * ((A_eq_tilde_candi > 0)' .* ub_base ...
                                                  + (A_eq_tilde_candi < 0)' .* lb_base);
                                delta_plus = A_eq_tilde_candi * ((A_eq_tilde_candi > 0)' .* (x_gen_base(:, indi) - lb_base) ...
                                             + (A_eq_tilde_candi < 0)' .* (x_gen_base(:, indi) - ub_base));
                                delta_minus = A_eq_tilde_candi * ((A_eq_tilde_candi > 0)' .* (x_gen_base(:, indi) - ub_base) ...
                                             + (A_eq_tilde_candi < 0)' .* (x_gen_base(:, indi) - lb_base));
                                x_cor_base = zeros(N_D - R_A, 1);
        
                                if Eq_tilde_candi_gen > b_eq_tilde_max(row_A_eq_tilde_candi)
                                    b_eq_k_tilde_best = [b_eq_k_tilde_lb + (delta_plus * (b_eq_tilde_min - A_eq_tilde * ((A_eq_tilde_candi > 0)' ...
                                                        .* lb_base + (A_eq_tilde_candi < 0)' .* ub_base + (A_eq_tilde_candi == 0)' .* x_gen_base(:, indi)))) ...
                                                        ./ (A_eq_tilde * ((A_eq_tilde_candi > 0)' .* (x_gen_base(:, indi) - lb_base) ...
                                                        + (A_eq_tilde_candi < 0)' .* (x_gen_base(:, indi) - ub_base))), ...
                                                        b_eq_k_tilde_lb + (delta_plus * (b_eq_tilde_max - A_eq_tilde * ((A_eq_tilde_candi > 0)' ...
                                                        .* lb_base + (A_eq_tilde_candi < 0)' .* ub_base + (A_eq_tilde_candi == 0)' .* x_gen_base(:, indi)))) ...
                                                        ./ (A_eq_tilde * ((A_eq_tilde_candi > 0)' .* (x_gen_base(:, indi) - lb_base) ...
                                                        + (A_eq_tilde_candi < 0)' .* (x_gen_base(:, indi) - ub_base)));
                                                        b_eq_k_tilde_lb, b_eq_k_tilde_ub];
                                    b_eq_k_tilde_min = max(min(b_eq_k_tilde_best, [], 2), [], 1);
                                    b_eq_k_tilde_max = min(max(b_eq_k_tilde_best, [], 2), [], 1);
                                    if b_eq_k_tilde_min <= b_eq_k_tilde_max
                                        b_eq_k_tilde = b_eq_k_tilde_min + rand * (b_eq_k_tilde_max - b_eq_k_tilde_min);
                                    else
                                        b_eq_k_tilde = b_eq_k_tilde_best(row_A_eq_tilde_candi, 1) + rand * (b_eq_k_tilde_best(row_A_eq_tilde_candi, 2)...
                                                       - b_eq_k_tilde_best(row_A_eq_tilde_candi, 1));
                                    end
                                    x_cor_base(A_eq_tilde_candi > 0) = (((b_eq_k_tilde - b_eq_k_tilde_lb) / delta_plus) ...
                                                                       * (x_gen_base(A_eq_tilde_candi > 0, indi) - lb_base(A_eq_tilde_candi > 0)) ...
                                                                       + lb_base(A_eq_tilde_candi > 0))';
                                    x_cor_base(A_eq_tilde_candi == 0) = (x_gen_base(A_eq_tilde_candi == 0))';
                                    x_cor_base(A_eq_tilde_candi < 0) = (((b_eq_k_tilde - b_eq_k_tilde_lb) / delta_plus) ...
                                                                       * (x_gen_base(A_eq_tilde_candi < 0, indi) - ub_base(A_eq_tilde_candi < 0)) ...
                                                                       + ub_base(A_eq_tilde_candi < 0))';
                                elseif Eq_tilde_candi_gen < b_eq_tilde_min(row_A_eq_tilde_candi)
                                    b_eq_k_tilde_best = [b_eq_k_tilde_ub + (delta_minus * (b_eq_tilde_min - A_eq_tilde * ((A_eq_tilde_candi > 0)' .* ub_base ...
                                                        + (A_eq_tilde_candi < 0)' .* lb_base + (A_eq_tilde_candi == 0)' .* x_gen_base(:, indi))) ./ (A_eq_tilde ...
                                                        * ((A_eq_tilde_candi > 0)' .* (x_gen_base(:, indi) - ub_base) + (A_eq_tilde_candi < 0)' .* ...
                                                        (x_gen_base(:, indi) - lb_base)))), ...
                                                        b_eq_k_tilde_ub + (delta_minus * (b_eq_tilde_max - A_eq_tilde * ((A_eq_tilde_candi > 0)' .* ub_base ...
                                                        + (A_eq_tilde_candi < 0)' .* lb_base + (A_eq_tilde_candi == 0)' .* x_gen_base(:, indi))) ./ (A_eq_tilde ...
                                                        * ((A_eq_tilde_candi > 0)' .* (x_gen_base(:, indi) - ub_base) + (A_eq_tilde_candi < 0)' .* ...
                                                        (x_gen_base(:, indi) - lb_base))));
                                                        b_eq_k_tilde_lb, b_eq_k_tilde_ub];
                                    b_eq_k_tilde_min = max(min(b_eq_k_tilde_best, [], 2), [], 1);
                                    b_eq_k_tilde_max = min(max(b_eq_k_tilde_best, [], 2), [], 1);
                                    if b_eq_k_tilde_min <= b_eq_k_tilde_max
                                        b_eq_k_tilde = b_eq_k_tilde_min + rand * (b_eq_k_tilde_max - b_eq_k_tilde_min);
                                    else
                                        b_eq_k_tilde = b_eq_k_tilde_best(row_A_eq_tilde_candi, 1) + rand * (b_eq_k_tilde_best(row_A_eq_tilde_candi, 2)...
                                                       - b_eq_k_tilde_best(row_A_eq_tilde_candi, 1));
                                    end
                                    x_cor_base(A_eq_tilde_candi > 0) = (((b_eq_k_tilde - b_eq_k_tilde_ub) / delta_minus) ...
                                                                       * (x_gen_base(A_eq_tilde_candi > 0, indi) - ub_base(A_eq_tilde_candi > 0)) ...
                                                                       + ub_base(A_eq_tilde_candi > 0))';
                                    x_cor_base(A_eq_tilde_candi == 0) = (x_gen_base(A_eq_tilde_candi == 0))';
                                    x_cor_base(A_eq_tilde_candi < 0) = (((b_eq_k_tilde - b_eq_k_tilde_ub) / delta_minus) ...
                                                                       * (x_gen_base(A_eq_tilde_candi < 0, indi) - lb_base(A_eq_tilde_candi < 0)) ...
                                                                       + lb_base(A_eq_tilde_candi < 0))';
                                end
                                x_cor(R_A + 1:end, indi) = x_cor_base;
                            end
                        end
                        x_cor(1:R_A, :) = Ab_eq_RREF(1:R_A, end) - A_eq_tilde * x_cor(R_A + 1:end, :);
    
                        for indi = 1:N_P
                            x_cor(abs(x_cor(:, indi) - lb) <= 1e-12, indi) = lb(abs(x_cor(:, indi) - lb) <= 1e-12);
                            x_cor(abs(x_cor(:, indi) - ub) <= 1e-12, indi) = ub(abs(x_cor(:, indi) - ub) <= 1e-12);
                        end
    
                        correction_info.is_feasible = all((x_cor - lb >= -1e-12) & (x_cor - ub <= 1e-12)) ...
                                                      & all(abs(A_eq * x_cor - b_eq) <= 1e-12);
                        correction_info.does_x_cor_exceed.by_bit = (x_cor - lb < -1e-12) | (x_cor - ub > 1e-12);
                        correction_info.does_x_cor_exceed.globally = any((x_cor - lb < -1e-12) | (x_cor - ub > 1e-12));
                        correction_info.is_equation_equal_to_b.by_bit = abs(A_eq * x_cor - b_eq) <= 1e-12;
                        correction_info.is_equation_equal_to_b.globally = all(abs(A_eq * x_cor - b_eq) <= 1e-12);

                        run = run + 1;
                        % Feasible
                        if all(correction_info.is_feasible)
                            break;
                        end
                        % Infeasible
                        if ~any(correction_info.is_feasible) && run > max_runtime
                            x_cor = [];
                            correction_info.is_feasible = false(1, N_P);
                            correction_info.does_x_cor_exceed.by_bit = true(N_D, N_P);
                            correction_info.does_x_cor_exceed.globally = true(1, N_P);
                            correction_info.is_equation_equal_to_b.by_bit = false(M, N_P);
                            correction_info.is_equation_equal_to_b.globally = false;
                            break;
                        end

                        x_gen = x_cor;
                    end

                end

            end            

        end 
        
    end

end

研究目标

    (1) 探究满足一般线性约束的生成随机数的修正方法;
    (2) 探究满足某些非线性约束的生成随机数修正方法;
    (3) 探究随机向量为离散向量和连续-离散混合向量时的生成随机数修正方法;
    (4) 将生成随机数修正方法应用到基于启发式算法的优化问题求解中,使得启发式算法能够始终在优化问题的可行域中搜寻问题的解,从而加快启发式优化算法的收敛速度。

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Academia1998

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值