优化问题 - GlobalSearch 未在 MATLAB 中生成初始向量

Optimization problem - GlobalSearch is not generating initial vector in MATLAB

简介

我要解决优化问题,包含一组常微分方程。更重要的是我需要找到 global 最小值。到目前为止,我只设法找到了几个局部最小值,但是对于如此复杂的问题,手动检查哪个是全局最小值是很棘手的。

描述

假设我有 3 个 Matlab 文件:

  1. Main.m - 它是通用脚本文件,它是所有其他文件的驱动程序
  2. ODE_set.m - 这包含我所有的 ODE 系统
  3. Opt_query.m - 这包含优化目标的定义,以及确定最小值所需的所有方程式。也从这个文件启动 ODE 求解器。

我可以用这段代码寻找局部最小值,它工作得很好,没有任何错误:

Main.m

global k1 k2 k3
x0 = [0.5 8 13];
lu =[ 0.9 25.74 60.9];
lb =[ 0.1 0.74 0.9];
[k,fval,exitflag,output] = fmincon('Opt_query',x0,[],[],[],[],lb,lu);
disp(k1)
disp(k2)
disp(k3)

然而,正如我上面提到的,我需要全局最小值,所以我开始尝试 GlobalSearch。这是我的代码:

x0 = [0.5 8 13];
lu =[ 0.9 25.74 60.9];
lb =[ 0.1 0.74 0.9];
gs = GlobalSearch;
problem = createOptimProblem('fmincon',Opt_query,x0,[],[],[],[],lb,lu);
[x,fval,exitflag,output] = run(gs,problem);

一个错误结束:

Not enough input arguments.

Error in Opt_query (line 3)

k1 = p(1)

这里是Opt_query.m的结构:

function q = Opt_query(p)
    global k1 k2 k3
    k1 = p(1)
    k2 = p(2)
    k3 = p(3)
    y0=[1 2 3]
    [t,y] = ode45(@ODE_set,[0, 130],y0,k1,k2,k3)
    t_steps=0:5:130;
    y_steps=interp1(t,y,t_steps);
    for j = 1:27
        Z = Z+ abs(y_steps(j,1)-5)+abs(y_steps(j,2)-7)+abs(y_steps(j,3)-9);
    end
    q = sqrt(Z);
end

这里是ODE_set.m的结构:

function dydt = ODE_set(t, y, k1, k2, k3)

F = 20.1;
A_in = 2.5;
V = 100;
k = 0.150; 
A = y(1);
B = y(2);
C = y(3);

n = numel(y);
dydt = zeros(n,1);
dydt(1) = F/V*(A_in - A) - k1*A^2;
dydt(1) = F/V*(B) - k2*B^2;
dydt(1) = F/V*(C) - k3*C^2;

问题

所以我的问题是 - 为什么当我单独使用 fmincon 时,它工作正常,但是当使用 GlobalSearch 启动时它不会生成初始 p 向量来保存参数优化?我是不是漏掉了什么,或者 GlobalSearch 需要不同的语法?

失误少


Opt_query中更改此

[t,y] = ode45(@ODE_set,[0, 130],y0,k1,k2,k3);

到这个

[t,y] = ode45(@(t,y)ODE_set(t,y, k1, k2, k3),[0, 130],y0);

After tspan = [0,30] you should only use the initial conditions, do not include k1, k2, k3

  • 只需使用具有 5 inputs t,y, k1, k2, k3 的函数 ODE_set 用两个输入创建一个新的 t , y 然后 k1, k2, k3 将被保留 作为固定输入
new_ODE_set = @(t, y)ODE_set(t, y, k1, k2, k3)
  • 这是 ode45 的语法
[t,y] = ode45(odefun,tspan,y0)

odefun 仅是 t, y 的函数

  • 因为 new_ODE_set 也是 t, y 的函数,所以现在可以用作 odefun

  • 但其实里面还有k1, k2, k3


for j = 1:27
   Z = Z+ abs(y_steps(j,1)-5)+abs(y_steps(j,2)-7)+abs(y_steps(j,3)-9);
end

Here you should initialize Z to zero before running the loop, like this

Z = 0;
for j = 1:27
    Z = Z+ abs(y_steps(j,1)-5)+abs(y_steps(j,2)-7)+abs(y_steps(j,3)-9);
end

In ODE_set you're only using index 1 for dydt

改变这个

dydt(1) = F/V*(A_in - A) - k1*A^2;
dydt(1) = F/V*(B) - k2*B^2;
dydt(1) = F/V*(C) - k3*C^2;

到这个

dydt(1) = F/V*(A_in - A) - k1*A^2;
dydt(2) = F/V*(B) - k2*B^2;
dydt(3) = F/V*(C) - k3*C^2;

总结


  • Main.m
global k1 k2 k3
x0 = [0.5 8 13];
lu =[ 0.9 25.74 60.9];
lb =[ 0.1 0.74 0.9];
gs = GlobalSearch;

problem = createOptimProblem('fmincon','objective',...
    @Opt_query,'x0',x0,'lb',lb,'ub',lu);

[x,fval,exitflag,output] = run(gs,problem);
disp(k1)
disp(k2)
disp(k3)

  • ODE_set.m
function dydt = ODE_set(t, y, k1, k2, k3)

    F = 20.1;
    A_in = 2.5;
    V = 100;
    k = 0.150; 
    A = y(1);
    B = y(2);
    C = y(3);

    n = numel(y);
    dydt = zeros(n,1);
    dydt(1) = F/V*(A_in - A) - k1*A^2;
    dydt(2) = F/V*(B) - k2*B^2;
    dydt(3) = F/V*(C) - k3*C^2;
end

  • Opt_query.m
function q = Opt_query(p)


    global k1 k2 k3
    k1 = p(1);
    k2 = p(2);
    k3 = p(3);
    y0=[1 2 3];



    [t,y] = ode45(@(t,y)ODE_set(t,y, k1, k2, k3),[0, 130],y0);
    t_steps=0:5:130;
    y_steps=interp1(t,y,t_steps);
    Z = 0;
    for j = 1:27
        Z = Z+ abs(y_steps(j,1)-5)+abs(y_steps(j,2)-7)+abs(y_steps(j,3)-9);
    end
    q = sqrt(Z);
end