exponenta event banner

Создание проблем эффективной оптимизации

Если проблема имеет целочисленные ограничения, solve требования intlinprog для получения раствора. Рекомендации по более быстрому решению или более чем целочисленным точкам см. в разделе Настройка целочисленного линейного программирования.

Прежде чем приступить к решению проблемы, иногда можно улучшить формулировку ограничений или цели проблемы. Обычно программа может создавать выражения для целевой функции или ограничений более быстро векторизированным образом, а не в цикле. Эта разность скоростей особенно велика, когда выражение оптимизации подвергается автоматическому дифференцированию; см. раздел Автоматическое дифференцирование в панели инструментов оптимизации.

Предположим, что ваша целевая функция

∑i=130∑j=130∑k=110xi,j,kbkci,j,

где x является переменной оптимизации, и b и c являются константами. Двумя общими способами формулирования этой целевой функции являются:

  • Использовать for цикл.

    x = optimvar('x',30,30,10);
    b = optimvar('b',10);
    c = optimvar('c',30,30);
    tic
    expr = optimexpr;
    for i = 1:30
        for j = 1:30
            for k = 1:10
                expr = expr + x(i,j,k)*b(k)*c(i,j);
            end
        end
    end
    toc
    Elapsed time is 307.459465 seconds.

    Здесь, expr содержит выражение целевой функции. Хотя этот метод прост, он может потребовать чрезмерного времени для петли через многие уровни for петли.

  • Используйте векторизированную инструкцию. Векторизованные операторы обычно выполняются быстрее, чем for цикл. Векторизированный оператор можно создать несколькими способами.

    • Расшириться b и c. Чтобы включить умножение по срокам, создайте константы того же размера, что и x.

      tic
      bigb = reshape(b,1,1,10);
      bigb = repmat(bigb,30,30,1);
      bigc = repmat(c,1,1,10);
      expr = sum(sum(sum(x.*bigb.*bigc)));
      toc
      Elapsed time is 0.013631 seconds.
    • Закольцовывание один раз b.

      tic
      expr = optimexpr;
      for k = 1:10
          expr = expr + sum(sum(x(:,:,k).*c))*b(k);
      end
      toc
      Elapsed time is 0.044985 seconds.
    • Создание выражения путем закольцовывания b и затем суммирование членов после цикла.

      tic
      expr = optimexpr(30,30,10);
      for k = 1:10
          expr(:,:,k) = x(:,:,k).*c*b(k);
      end
      expr = sum(expr(:));
      toc
      Elapsed time is 0.039518 seconds.

Обратите внимание на разницу скоростей векторизированной и невекторизированной реализации примера ограниченной электростатической нелинейной оптимизации, основанной на проблемах. Этот пример был синхронизирован с использованием автоматического дифференцирования в R2020b.

N = 30;
x = optimvar('x',N,'LowerBound',-1,'UpperBound',1);
y = optimvar('y',N,'LowerBound',-1,'UpperBound',1);
z = optimvar('z',N,'LowerBound',-2,'UpperBound',0);
elecprob = optimproblem;
elecprob.Constraints.spherec = (x.^2 + y.^2 + (z+1).^2) <= 1;
elecprob.Constraints.plane1 = z <= -x-y;
elecprob.Constraints.plane2 = z <= -x+y;
elecprob.Constraints.plane3 = z <= x-y;
elecprob.Constraints.plane4 = z <= x+y;

rng default % For reproducibility
x0 = randn(N,3);
for ii=1:N
    x0(ii,:) = x0(ii,:)/norm(x0(ii,:))/2;
    x0(ii,3) = x0(ii,3) - 1;
end
init.x = x0(:,1);
init.y = x0(:,2);
init.z = x0(:,3);
opts = optimoptions('fmincon','Display','off');

tic
energy = optimexpr(1);
for ii = 1:(N-1)
    jj = (ii+1):N; % Vectorized
    tempe = (x(ii) - x(jj)).^2 + (y(ii) - y(jj)).^2 + (z(ii) - z(jj)).^2;
    energy = energy + sum(tempe.^(-1/2));
end
elecprob.Objective = energy;
disp('Vectorized computation time:')
[sol,fval,exitflag,output] = solve(elecprob,init,'Options',opts);
toc
Vectorized computation time:
Elapsed time is 1.838136 seconds.
tic
energy2 = optimexpr(1); % For nonvectorized comparison
for ii = 1:(N-1)
    for jjj = (ii+1):N; % Not vectorized
        energy2 = energy2 + ((x(ii) - x(jjj))^2 + (y(ii) - y(jjj))^2 + (z(ii) - z(jjj))^2)^(-1/2);
    end
end
elecprob.Objective = energy2;
disp('Non-vectorized computation time:')
[sol,fval,exitflag,output] = solve(elecprob,init,'Options',opts);
toc
Non-vectorized computation time:
Elapsed time is 204.615210 seconds.

Векторизированная версия примерно в 100 раз быстрее, чем не векторизированная версия.

Связанные темы