Создайте эффективные задачи оптимизации

Когда проблема имеет целочисленные ограничения, solve вызовы intlinprog получить решение. Для предложений при получении более быстрого решения или большего количества целочисленных допустимых точек, смотрите Настраивающееся Целочисленное Линейное Программирование.

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

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

i=130j=130k=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 раз быстрее, чем невекторизованная версия.

Похожие темы