MATLAB - написание целевой функции для fmincon()

Мне нужно минимизировать следующую функцию

nDOF, nprocs и T взяты из первых двух столбцов этой таблицы

Итак, у меня есть следующие векторы в MATLAB

nDOF =
        3993
        3993
        3993
        3993
        3993
        3993
        3993
        3993
        7623
        7623
        7623
        7623
        7623
        7623
        7623
        7623

nprocs =
     1
     2
     3
     4
     6
     8
    12
    24
     1
     2
     3
     4
     6
     8
    12
    24

vals = 
    0.6564
    0.2569
    0.2719
    0.1743
    0.1305
    0.1230
    0.1739
    0.1147
    1.1998
    0.5088
    0.6419
    0.2899
    0.2192
    0.2033
    0.2126
    0.1821

И я хотел минимизировать функцию $F$ с помощью функции fmincon следующим образом:

fmincon(@(theta) objFunctionMatAssemble(theta(1), theta(2), theta(3), theta(4), ndofIN, nprocsIN, vals), [0 0 0 0]', [], [], [], [], [0 0 0 0], [+inf +inf +inf +inf] )

Код объекта objFunctionMatAssemble:

function [t] = objFunctionMatAssemble(alpha, beta, gamma, delta, ndofIN, nprocsIN, vals)
    t = 0;
    for i=1:length(nprocsIN)
        t = t + alpha*ndofIN^beta + gamma*((ndofIN(i)^delta)/nprocsIN(i) - vals(i))^2;
    end
end

Проблема в том, что я получаю следующую ошибку:

>> fmincon(@(theta) objFunctionMatAssemble(theta(1), theta(2), theta(3), theta(4), ndofIN, nprocsIN, vals), [0 0 0 0]', [], [], [], [], [0 0 0 0], [+inf +inf +inf +inf] )
Error using  ^ 
Inputs must be a scalar and a square matrix.
To compute elementwise POWER, use POWER (.^) instead.

Error in objFunctionMatAssemble (line 4)
        t = t + alpha*ndofIN^beta + gamma*((ndofIN(i)^delta)/nprocsIN(i) - vals(i))^2;

Error in @(theta)objFunctionMatAssemble(theta(1),theta(2),theta(3),theta(4),ndofIN,nprocsIN,vals)

Error in fmincon (line 535)
      initVals.f = feval(funfcn{3},X,varargin{:});

Caused by:
    Failure in initial objective function evaluation. FMINCON cannot continue.

Проблема, видимо, в моей целевой функции, но я не могу написать ее правильно, несмотря на попытки несколько раз. Я видел какое-то решение здесь на SO, но даже если моя "функция замыкания" принимает только один аргумент и вызывает другой, его формат по-прежнему неверен.

Не могли бы вы помочь мне с этим?

1 ответ

Решение

Вы забыли проиндексировать ndofIN в цикле (вы пишете ndofIN^beta, который должен быть ndofIN(i)^beta).

Теперь оператор ^ в MATLAB означает матрицу мощности. Для скалярного / скалярного ввода эта операция такая же, как и для обычного возведения в степень, но для матричного / скалярного ввода это не совсем то же самое. В вашем случае MATLAB пытается возвести в степень вектор ndofIN с beta - это недопустимо, поскольку мощность матрицы определяется только для квадратных матриц. Вот почему вы получаете эту ошибку.

Очевидно, это не совсем то, что вы намереваетесь сделать - вы хотите поэлементного возведения в степень (.^). Используя это, вы можете значительно упростить и ускорить выполнение вашей целевой функции - просто напишите эту целевую функцию следующим образом:

function t = objFunctionMatAssemble(alpha, ...
                                    beta, ...
                                    gamma, ...
                                    delta, ...
                                    ndofIN, ...
                                    nprocsIN, ...
                                    vals) 

    t = alpha *  ndofIN.^beta + ...
        gamma * (ndofIN.^delta)./nprocsIN - vals;

    t = t.' * t;

end

ПРИМЕЧАНИЕ. В исходной функции также есть несоответствие в скобках. То есть ваши круглые скобки делают вашу целевую функцию чем-то отличным от того, что вы показали в вопросе:

% your version
t = t +  alpha*ndofIN^beta + gamma*((ndofIN(i)^delta)/nprocsIN(i) - vals(i))^2;

% what's in the image
t = t + (alpha*ndofIN^beta + gamma* (ndofIN(i)^delta)/nprocsIN(i) - vals(i))^2;

NB2: Вы также можете написать свою целевую функцию следующим образом:

function t = objFunctionMatAssemble2(theta, ...
                                     ndofIN, ...
                                     nprocsIN, ...
                                     TIN)                                      

    N = bsxfun(@power, ndofIN, theta([2 4]).');        
    t = [N(:,1) N(:,2)./nprocsIN] * theta([1 3]) - TIN;        
    t = t.' * t;

end

так что вашей целевой функции не нужно так много аргументов. Но хорошо, это зависит от ваших вкусов.

Другие вопросы по тегам