Рассмотрите или измените задачи оптимизации

Рассмотрите проблему Используя showproblem или writeproblem

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

prob = optimproblem;
x = optimvar('x',2,'LowerBound',0);
prob.Objective = x(1) - 2*x(2);
prob.Constraints.cons1 = x(1) + 2*x(2) <= 4;
prob.Constraints.cons2 = -x(1) + x(2) <= 1;

showproblem(prob)
  OptimizationProblem : 

	minimize :
       x(1) - 2*x(2)

	subject to cons1:
       x(1) + 2*x(2) <= 4

	subject to cons2:
       -x(1) + x(2) <= 1

	variable bounds:
       0 <= x(1)
       0 <= x(2)

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

Измените решатель по умолчанию или опции

Чтобы попытаться улучшить решение или скорость решения, исследуйте и измените решатель по умолчанию или опции.

Чтобы видеть решатель по умолчанию и опции, используйте optimoptions(prob). Например,

rng default
x = optimvar('x',3,'LowerBound',0);
expr = sum((rand(3,1).*x).^2);
prob = optimproblem('Objective',expr);
prob.Constraints.lincon = sum(sum(randn(size(x)).*x)) <= randn;
options = optimoptions(prob)
options = 

  lsqlin options:

   Options used by current Algorithm ('interior-point'):
   (Other available algorithms: 'trust-region-reflective')

   Set properties:
     No options set.

   Default properties:
              Algorithm: 'interior-point'
    ConstraintTolerance: 1.0000e-08
                Display: 'final'
           LinearSolver: 'auto'
          MaxIterations: 200
    OptimalityTolerance: 1.0000e-08
          StepTolerance: 1.0000e-12

   Show options not used by current Algorithm ('interior-point')

Решателем по умолчанию для этой проблемы является lsqlin, и вы видите опции по умолчанию.

Чтобы изменить решатель, установите пару "имя-значение" 'Solver' в solve. Чтобы видеть применимые опции для другого решателя, используйте optimoptions, чтобы передать текущие опции другому решателю. Например, продолжая проблему,

options = optimoptions('quadprog',options)
options = 

  quadprog options:

   Options used by current Algorithm ('interior-point-convex'):
   (Other available algorithms: 'trust-region-reflective')

   Set properties:
    ConstraintTolerance: 1.0000e-08
          MaxIterations: 200
    OptimalityTolerance: 1.0000e-08
          StepTolerance: 1.0000e-12

   Default properties:
              Algorithm: 'interior-point-convex'
                Display: 'final'
           LinearSolver: 'auto'

   Show options not used by current Algorithm ('interior-point-convex')

Чтобы изменить опции, используйте optimoptions или запись через точку, чтобы установить опции и передать опции solve в паре "имя-значение" 'Options'. Продолжение примера,

options.Display = 'iter';
sol = solve(prob,'Options',options,'Solver','quadprog');
 Iter            Fval  Primal Infeas    Dual Infeas  Complementarity  
    0    1.500359e+00   3.068423e-01   2.275437e+00     2.500000e-01  
    1    1.728717e-01   0.000000e+00   7.719860e-03     3.637874e-02  
    2    2.604108e-02   0.000000e+00   0.000000e+00     5.245260e-03  
    3    7.822161e-03   0.000000e+00   2.775558e-17     1.407915e-03  
    4    2.909218e-03   0.000000e+00   6.938894e-18     2.070784e-04  
    5    1.931264e-03   0.000000e+00   1.734723e-18     2.907724e-05  
    6    1.797508e-03   0.000000e+00   2.602085e-18     4.083167e-06  
    7    1.775398e-03   0.000000e+00   4.336809e-19     5.102453e-07  
    8    1.772971e-03   0.000000e+00   2.632684e-19     3.064243e-08  
    9    1.772848e-03   0.000000e+00   5.228973e-19     4.371356e-11  

Minimum found that satisfies the constraints.

Optimization completed because the objective function is non-decreasing in 
feasible directions, to within the value of the optimality tolerance,
and constraints are satisfied to within the value of the constraint tolerance.

Исправьте проблему Misspecified

Чтобы проверять, что ваша проблема правильна, рассмотрите все ее аспекты. Например, создайте задачу оптимизации, чтобы решить проблему Судоку путем выполнения этого скрипта.

x = optimvar('x',9,9,9,'LowerBound',0,'UpperBound',1);
cons1 = sum(x,1) == 1;
cons2 = sum(x,2) == 1;
cons3 = sum(x,3) == 1;
prob = optimproblem;
prob.Constraints.cons1 = cons1;
prob.Constraints.cons2 = cons2;
prob.Constraints.cons3 = cons3;
mul = ones(1,1,9);
mul = cumsum(mul,3);
prob.Objective = sum(sum(sum(x,1),2).*mul);
cons4 = optimconstr(3,3,9);

for u = 1:3
    for v = 1:3
        arr = x(3*(u-1)+1:3*(u-1)+3,3*(v-1)+1:3*(v-1)+3,:);
        cons4(u,v,:) = sum(sum(arr,1),2) <= ones(1,1,9);
    end
end
prob.Constraints.cons4 = cons4;

B = [1,2,2;
1,5,3;
1,8,4;
2,1,6;
2,9,3;
3,3,4;
3,7,5;
4,4,8;
4,6,6;
5,1,8;
5,5,1;
5,9,6;
6,4,7;
6,6,5;
7,3,7;
7,7,6;
8,1,4;
8,9,8;
9,2,3;
9,5,4;
9,8,2];

for u = 1:size(B,1)
    x.LowerBound(B(u,1),B(u,1),B(u,1)) = 1;
end

Этот скрипт имеет некоторые ошибки, которые можно найти путем исследования переменных, цели и ограничений. Во-первых, исследуйте переменную x.

x
x = 

  9×9×9 OptimizationVariable array with properties:

 Array-wide properties:
          Name: 'x'
          Type: 'continuous'
    IndexNames: {{}  {}  {}}

 Elementwise properties:
    LowerBound: [9×9×9 double]
    UpperBound: [9×9×9 double]

See variables with showvar.
See bounds with showbounds.

Это отображение показывает, что тип переменной непрерывен. Переменная должна быть оцененным целым числом. Измените тип.

x.Type = 'integer'
x = 

  9×9×9 OptimizationVariable array with properties:

 Array-wide properties:
          Name: 'x'
          Type: 'integer'
    IndexNames: {{}  {}  {}}

 Elementwise properties:
    LowerBound: [9×9×9 double]
    UpperBound: [9×9×9 double]

See variables with showvar.
See bounds with showbounds.

Проверяйте границы. Должна быть 21 нижняя граница со значением 1, один для каждой строки B. Поскольку x является большим массивом, запишите границы в файл вместо того, чтобы отобразить их в командной строке.

writebounds(x,'xbounds.txt')

Ищите файл xbounds.txt все экземпляры 1 <=. Только девять нижних границ, имеющих значение 1, в переменных x(1,1,1), x(2,2,2), …, x(9,9,9). Чтобы исследовать это несоответствие, исследуйте код, где вы устанавливаете нижние границы:

for u = 1:size(B,1)
    x.LowerBound(B(u,1),B(u,1),B(u,1)) = 1;
end

Строка в цикле должна сказать x.LowerBound(B(u,1),B(u,2),B(u,3)) = 1;. Сбросьте все нижние границы, чтобы обнулить, затем запустите исправленный код.

x.LowerBound = 0;
for u = 1:size(B,1)
    x.LowerBound(B(u,1),B(u,2),B(u,3)) = 1;
end
writebounds(x,'xbounds.txt')

xbounds.txt теперь имеет правильное количество записей нижней границы, которые равняются 1.

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

writeexpr(prob.Objective,'objectivedescription.txt')
    x(1, 1, 1) + x(2, 1, 1) + x(3, 1, 1) + x(4, 1, 1) + x(5, 1, 1) + x(6, 1, 1) + x(7, 1, 1) + x(8,
    1, 1) + x(9, 1, 1) + x(1, 2, 1) + x(2, 2, 1) + x(3, 2, 1) + x(4, 2, 1) + x(5, 2, 1) + x(6, 2,
    ...
    9*x(7, 8, 9) + 9*x(8, 8, 9) + 9*x(9, 8, 9) + 9*x(1, 9, 9) + 9*x(2, 9, 9) + 9*x(3, 9, 9) +
    9*x(4, 9, 9) + 9*x(5, 9, 9) + 9*x(6, 9, 9) + 9*x(7, 9, 9) + 9*x(8, 9, 9) + 9*x(9, 9, 9)

Целевая функция выглядит разумной, потому что это - сумма скалярных выражений.

Запишите ограничения в файлы для исследования.

writeconstr(prob.Constraints.cons1,'cons1.txt')
writeconstr(prob.Constraints.cons2,'cons2.txt')
writeconstr(prob.Constraints.cons3,'cons3.txt')
writeconstr(prob.Constraints.cons4,'cons4.txt')

Рассмотрите cons4.txt, и вы видите ошибку. Все ограничения являются неравенствами, а не равенствами. Исправьте строки кода, которые создают это ограничение и помещают исправленное ограничение в проблему.

cons4 = optimconstr(3,3,9);

for u = 1:3
    for v = 1:3
        arr = x(3*(u-1)+1:3*(u-1)+3,3*(v-1)+1:3*(v-1)+3,:);
        cons4(u,v,:) = sum(sum(arr,1),2) == ones(1,1,9);
    end
end
prob.Constraints.cons4 = cons4;

После этих изменений можно успешно решить проблему.

sol = solve(prob);
x = round(sol.x);
y = ones(size(x));
for k = 2:9
    y(:,:,k) = k; % multiplier for each depth k
end
S = x.*y; % multiply each entry by its depth
S = sum(S,3); % S is 9-by-9 and holds the solved puzzle

drawSudoku(S)

Дублирующееся имя переменной

Если вы воссоздаете переменную, но уже имеете выражение, которое использует старую переменную, то можно получить ошибки при слиянии выражений в одну проблему. Смотрите Переменные с Запрещенными Двойными названиями.

Смотрите также

| | | | | | | | | | | | |

Похожие темы