How to solve a non-linear optimization problem with matrix and vector decision variables?

9 Ansichten (letzte 30 Tage)
Hey folks. I'm somewhat new to optimizations and got stuck trying to solve an optimization problem where I have two decision variables: one is a matrix and the other is a vector. While my objective function is a rather simple linear cost function, and most of my constraints are also rather easy to handle, there is one somewhat lengthy non-linear constraint that seems to cause issues.
The problem looks as follows:
In the following, capital symbols are matrices, vectors are indicated by arrows, and everything else is a scalar. Dimensions of the vectors and matrix variables are as follows:
B is an LxL matrix of real numbers
In my specific example, the values of L and N are 39 and 46, but in other examples they may go up to several hundreds.
Objective function: minimize total costs resulting from changes in b and p
min C = sum(b_ll * c_l) + sum(p_n * c_n), with b_ll as an element of matrix B [LxL] and p_n as an element of p [Nx1]
Constraints:
  1. Min and max allowed values for elements of DeltaB-matrix: delta b_l must be between their min and max values
  2. All elements outside of the diagonal of DeltaB-matrix must remain zero:
  3. Min and max allowed values in elements of p-vector: Delta p values must be within min and max values
  4. Changes in p-elements must sum up to zero: Sum of changes in p-elements must equal zero
  5. And now the somewhat convoluted non-linear constraint which is rather difficult to explain:
Here's an MWE to showcase how I hoped to solve this using ga (I originally started with fmincon but that threw errors and recommended ga):
%% Input values
B = [ 10 -1 -2 -3 -4;...
-1 19 -5 -6 -7;...
-2 -5 24 -8 -9;...
-3 -6 -8 27 -10;...
-4 -7 -9 -10 30];
A = [ 1 -1 0 0;...
0 1 -1 0;...
0 0 1 -1;...
1 0 0 -1;...
0 1 0 -1];
p = [-60; 160; -200; 100];
L = size(B,1); % = 5
N = size(A,2); % = 4
cost_per_b = 0.01; % same for all b_ij
delta_B_min = diag(-10*ones(L,1));
delta_B_max = diag(10*ones(L,1));
delta_p_min = -5*ones(N,1);
delta_p_max = 5*ones(N,1);
m = 120*ones(L,1);
cost_per_p = 1; % same for all elements of delta_p
mstart = -B * A * (A' * B * A)^-1 * p; % to give an idea for m-ranges
%% Optimization problem
% Decision variables
delta_B = optimvar('delta_B',L,L);
delta_p = optimvar('delta_p',N,1);
% Starting points
x0.delta_B = zeros(L);
x0.delta_p = zeros(N,1);
% Constraints
delta_B.LowerBound = delta_B_min;
delta_B.UpperBound = delta_B_max;
delta_p.LowerBound = delta_p_min;
delta_p.UpperBound = delta_p_max;
pbalance_cons = sum(delta_p) == 0;
nonlincons_pos = ...
((B + delta_B) * A * (A' * (B + delta_B) * A)^(-1)) * (p + delta_p)...
<= m;
nonlincons_neg = ...
((B + delta_B) * A * (A' * (B + delta_B) * A)^(-1)) * (p + delta_p)...
>= -m;
% Objective
objective = cost_per_b*sum((delta_B(:)')) + cost_per_p*sum(delta_p');
% Create optimization problem
prob = optimproblem('Objective',objective);
prob.Constraints.pbalance = pbalance_cons;
prob.Constraints.nonlincons_pos = nonlincons_pos;
prob.Constraints.nonlincons_neg = nonlincons_neg;
opts = optimoptions('ga');
show(prob);
% Solve optimization problem
[sol,fval,exitflag,output] = solve(prob,x0,opts);
While the output of show() looks fine (imo), the last line unfortunately produces an output error:
Error using optim.internal.problemdef.ProblemImpl/solveImpl
The value of 'GlobalSolver' is invalid. GlobalSolver must be a MultiStart or GlobalSearch object.
Error in optim.problemdef.OptimizationProblem/solve
Error in mwe_optimization (line 57)
[sol,fval,exitflag,output] = solve(prob,x0,opts);
I've tried to understand how to turn this into a MultiStart or GlobalSearch but I don't quite get what makes my optimization problem so difficult for just regular ga or other solvers. Why do I need MultiStart or GlobalSearch for this? And if it is really necessary, how do I set GlobalSolver accordingly?

Akzeptierte Antwort

Torsten
Torsten am 8 Feb. 2023
Bearbeitet: Torsten am 9 Feb. 2023
I turned deltaB into a diagonal matrix.
I changed m to 130 and it works. Are you sure a solution exists for m = 120 ?
%% Input values
B = [ 10 -1 -2 -3 -4;...
-1 19 -5 -6 -7;...
-2 -5 24 -8 -9;...
-3 -6 -8 27 -10;...
-4 -7 -9 -10 30];
A = [ 1 -1 0 0;...
0 1 -1 0;...
0 0 1 -1;...
1 0 0 -1;...
0 1 0 -1];
p = [-60; 160; -200; 100];
L = size(B,1); % = 5
N = size(A,2); % = 4
cost_per_b = 0.01; % same for all b_ij
delta_B_min = -10*ones(L,1);
delta_B_max = 10*ones(L,1);
delta_p_min = -5*ones(N,1);
delta_p_max = 5*ones(N,1);
m = 130*ones(L,1);
cost_per_p = 1; % same for all elements of delta_p
mstart = -B * A * (A' * B * A)^-1 * p % to give an idea for m-ranges
mstart = 5×1
15 -130 45 5 -55
%% Optimization problem
% Decision variables
delta_B = optimvar('delta_B',L,1);
delta_p = optimvar('delta_p',N,1);
% Starting points
x0.delta_B = zeros(L,1);
x0.delta_p = zeros(N,1);
% Constraints
delta_B.LowerBound = delta_B_min;
delta_B.UpperBound = delta_B_max;
delta_p.LowerBound = delta_p_min;
delta_p.UpperBound = delta_p_max;
pbalance_cons = sum(delta_p) == 0;
nonlincons_pos = ...
((B + diag(delta_B)) * A * (A' * (B + diag(delta_B)) * A)^(-1)) * (p + delta_p)...
<= m;
nonlincons_neg = ...
((B + diag(delta_B)) * A * (A' * (B + diag(delta_B)) * A)^(-1)) * (p + delta_p)...
>= -m;
% Objective
objective = cost_per_b*sum(delta_B') + cost_per_p*sum(delta_p');
% Create optimization problem
prob = optimproblem('Objective',objective);
prob.Constraints.pbalance = pbalance_cons;
prob.Constraints.nonlincons_pos = nonlincons_pos;
prob.Constraints.nonlincons_neg = nonlincons_neg;
%opts = optimoptions('ga');
show(prob);
OptimizationProblem : Solve for: delta_B, delta_p minimize : 0.01*delta_B(1) + 0.01*delta_B(2) + 0.01*delta_B(3) + 0.01*delta_B(4) + 0.01*delta_B(5) + delta_p(1) + delta_p(2) + delta_p(3) + delta_p(4) subject to pbalance: delta_p(1) + delta_p(2) + delta_p(3) + delta_p(4) == 0 subject to nonlincons_pos: arg_LHS <= extraParams{7} where: arg1 = (extraParams{6} + delta_p); arg_LHS = ((((extraParams{4} + diag(delta_B)) * extraParams{5}) * ((extraParams{2} * (extraParams{1} + diag(delta_B))) * extraParams{3})^-1) * arg1); extraParams{1}: 10 -1 -2 -3 -4 -1 19 -5 -6 -7 -2 -5 24 -8 -9 -3 -6 -8 27 -10 : : extraParams{2}: 1 0 0 1 0 -1 1 0 0 1 0 -1 1 0 0 0 0 -1 -1 -1 extraParams{3}: 1 -1 0 0 0 1 -1 0 0 0 1 -1 1 0 0 -1 0 1 0 -1 extraParams{4}: 10 -1 -2 -3 -4 -1 19 -5 -6 -7 -2 -5 24 -8 -9 -3 -6 -8 27 -10 : : extraParams{5}: 1 -1 0 0 0 1 -1 0 0 0 1 -1 1 0 0 -1 0 1 0 -1 extraParams{6}: -60 160 -200 100 extraParams{7}: 130 130 130 130 130 subject to nonlincons_neg: arg_LHS >= extraParams{7} where: arg1 = (extraParams{6} + delta_p); arg_LHS = ((((extraParams{4} + diag(delta_B)) * extraParams{5}) * ((extraParams{2} * (extraParams{1} + diag(delta_B))) * extraParams{3})^-1) * arg1); extraParams{1}: 10 -1 -2 -3 -4 -1 19 -5 -6 -7 -2 -5 24 -8 -9 -3 -6 -8 27 -10 : : extraParams{2}: 1 0 0 1 0 -1 1 0 0 1 0 -1 1 0 0 0 0 -1 -1 -1 extraParams{3}: 1 -1 0 0 0 1 -1 0 0 0 1 -1 1 0 0 -1 0 1 0 -1 extraParams{4}: 10 -1 -2 -3 -4 -1 19 -5 -6 -7 -2 -5 24 -8 -9 -3 -6 -8 27 -10 : : extraParams{5}: 1 -1 0 0 0 1 -1 0 0 0 1 -1 1 0 0 -1 0 1 0 -1 extraParams{6}: -60 160 -200 100 extraParams{7}: -130 -130 -130 -130 -130 variable bounds: -10 <= delta_B(1) <= 10 -10 <= delta_B(2) <= 10 -10 <= delta_B(3) <= 10 -10 <= delta_B(4) <= 10 -10 <= delta_B(5) <= 10 -5 <= delta_p(1) <= 5 -5 <= delta_p(2) <= 5 -5 <= delta_p(3) <= 5 -5 <= delta_p(4) <= 5
% Solve optimization problem
[sol,fval,exitflag,output] = solve(prob,x0);%,opts);
Solving problem using fmincon. Local minimum possible. Constraints satisfied. fmincon stopped because the size of the current step is less than the value of the step size tolerance and constraints are satisfied to within the value of the constraint tolerance.
  6 Kommentare
Torsten
Torsten am 13 Feb. 2023
Bearbeitet: Torsten am 13 Feb. 2023
Next time you ask a question please supply a complete executable code for which the problem appears so that we don't need to puzzle together the parts in order to test a possible solution.
%% Input values
B = [ -10 0 0 0 0;...
0 -11 0 0 0;...
0 0 -12 0 0;...
0 0 0 -13 0;...
0 0 0 0 -14];
p = [1.32; -1.7; -2.0; 2.3];
A = [ 1 -1 0 0;...
0 1 -1 0;...
0 0 1 -1;...
1 0 0 -1;...
0 1 0 -1];
L = size(B,1); % = 5
N = size(A,2); % = 4
cost_per_b = 0.01; % same for all b_ij
delta_b_min = -10*ones(L,1);
delta_b_max = 10*ones(L,1);
delta_p_min = -5*ones(N,1);
delta_p_max = 5*ones(N,1);
cost_per_p = 1; % same for all elements of delta_p
mstart = -B * A * (A' * B * A)^-1 * p; % to give an idea for m-ranges
% Give the elements 1,3,4,5 some room but restrict element 2
[~,m_max_idx] = max(abs(mstart));
m = abs(mstart) * 2;
m(m_max_idx) = 0.9*abs(mstart(m_max_idx));
%% Optimization problem
% Decision variables
delta_b = optimvar('delta_b',L,1);
delta_p = optimvar('delta_p',N,1);
% Starting points
x0.delta_b = zeros(L,1);
x0.delta_p = zeros(N,1);
% Constraints
delta_b.LowerBound = delta_b_min;
delta_b.UpperBound = delta_b_max;
delta_p.LowerBound = delta_p_min;
delta_p.UpperBound = delta_p_max;
pbalance_cons = sum(delta_p) == 0;
inv(A'*(B+x0.delta_b)*A)
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = 1.816655e-17.
ans = 4×4
1.0e+14 * -1.7643 -1.7643 -1.7643 -1.7643 -1.7643 -1.7643 -1.7643 -1.7643 -1.7643 -1.7643 -1.7643 -1.7643 -1.7643 -1.7643 -1.7643 -1.7643
rank(A'*(B+x0.delta_b)*A)
ans = 3
nonlincons = @(x,y)abs(((B + diag(x)) * A * pinv(A' * (B + diag(x)) * A) ) * (p + y));
nonlincons = fcn2optimexpr(nonlincons,delta_b,delta_p);
nonlincons_abs = nonlincons <= m;
% Objective
objective = cost_per_b*sum(delta_b') + cost_per_p*sum(delta_p');
% Create optimization problem
prob = optimproblem('Objective',objective);
prob.Constraints.pbalance = pbalance_cons;
prob.Constraints.nonlincons_pos = nonlincons_abs;
show(prob);
OptimizationProblem : Solve for: delta_b, delta_p minimize : 0.01*delta_b(1) + 0.01*delta_b(2) + 0.01*delta_b(3) + 0.01*delta_b(4) + 0.01*delta_b(5) + delta_p(1) + delta_p(2) + delta_p(3) + delta_p(4) subject to pbalance: delta_p(1) + delta_p(2) + delta_p(3) + delta_p(4) == 0 subject to nonlincons_pos: arg_LHS <= extraParams{1} where: anonymousFunction1 = @(x,y)abs(((B+diag(x))*A*pinv(A'*(B+diag(x))*A))*(p+y)); arg_LHS = anonymousFunction1(delta_b, delta_p); extraParams{1}: 3.1700 1.0000 2.2320 3.7000 3.6200 variable bounds: -10 <= delta_b(1) <= 10 -10 <= delta_b(2) <= 10 -10 <= delta_b(3) <= 10 -10 <= delta_b(4) <= 10 -10 <= delta_b(5) <= 10 -5 <= delta_p(1) <= 5 -5 <= delta_p(2) <= 5 -5 <= delta_p(3) <= 5 -5 <= delta_p(4) <= 5
% Solve optimization problem
options = optimoptions(prob);
options.MaxFunctionEvaluations = 3e4;
options.MaxIterations = 1500;
[sol,fval,exitflag,output] = solve(prob,x0,'Options',options);
Solving problem using fmincon. Local 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.
Oliver Pohl
Oliver Pohl am 14 Feb. 2023
Yes, you're right. I really did try to make my original example work though. Sorry for the back and forth.
Using options like that works now, thank you. Solver still exceeds the (increased) function evaluation limit, but I think my error lies elsewhere so I'll mark this as solved, since my original question has been thoroughly answered.

Melden Sie sich an, um zu kommentieren.

Weitere Antworten (0)

Produkte


Version

R2022b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by