Проблема оптимизации - GlobalSearch не генерирует начальный вектор в MATLAB - PullRequest
0 голосов
/ 31 мая 2019

INTRO

Мне нужно решить задачу оптимизации, содержащую набор обыкновенных дифференциальных уравнений.Что еще мне нужно, чтобы найти глобальный минимум.Пока мне удалось найти лишь несколько локальных минимумов, но вручную проверить, какой из них глобален, сложно для такой сложной проблемы.

Описание

Допустим, у меня есть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);

Он заканчивается ошибкой :

Недостаточно входных аргументов.

Ошибка в Opt_query (строка 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 требуется другой синтаксис?

1 Ответ

1 голос
/ 31 мая 2019

Несколько ошибок


В 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);

После tspan = [0,30] вы должны использовать только начальные условия, выполните не включает k1, k2, k3

  • Просто возьмите функцию ODE_set, которая имеет 5 inputs t,y, k1, k2, k3 создайте новый с двумя входами 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

Здесь вы должны инициализировать Z до нуля перед запуском цикла, как это

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

В ODE_set вы используете только индекс 1 для 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...