show
или write
После того, как вы создаете задачу оптимизации, можно просмотреть ее формулировку при помощи show
. Для больших задач используйте write
вместо этого. Для примера,
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; show(prob)
OptimizationProblem : Solve for: x 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.
Чтобы проверить, что ваша проблема верна, проверьте все ее аспекты. Например, создайте задачу оптимизации, чтобы решить задачу Sudoku, запустив этот скрипт.
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 show. 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 show. 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.
Исследуйте целевую функцию. Выражение целевой функции большое, поэтому запишите выражение в файл.
write(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)
Целевая функция выглядит разумной, потому что это сумма скалярных выражений.
Запишите ограничения в файлы для проверки.
write(prob.Constraints.cons1,'cons1.txt') write(prob.Constraints.cons2,'cons2.txt') write(prob.Constraints.cons3,'cons3.txt') write(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
| show
| showbounds
| write
| writebounds