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.
Чтобы проверять, что ваша проблема правильна, рассмотрите все ее аспекты. Например, создайте задачу оптимизации, чтобы решить проблему Судоку путем выполнения этого скрипта.
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)
Если вы воссоздаете переменную, но уже имеете выражение, которое использует старую переменную, то можно получить ошибки при слиянии выражений в одну проблему. Смотрите Переменные с Запрещенными Двойными названиями.
OptimizationConstraint
| OptimizationExpression
| OptimizationProblem
| OptimizationVariable
| showbounds
| showconstr
| showexpr
| showproblem
| showvar
| writebounds
| writeconstr
| writeexpr
| writeproblem
| writevar