Optimization solver fmincon option

3 次查看(过去 30 天)
Fada
Fada 2022-3-14
评论: Fada 2022-3-16
I am trying to use Matlab to solve an optimal economic dispatch problem. Two generators and one battery.
I used a pair of integer variables for battery status, 0/1.
Initially I used the "solve" function but it complained integer/nonlinear problem should use fmincon.
However, I couldn't make it work. Which function should I use to get it solved?
%test economic disptach with 2 genertors and one battery
Load=[350; 607; 380; 605];%hourly load level, only study 4 hours
n = length(Load); %use load's demension to define the size
basegen_cost=[10; 10; 10; 10];%base load generator is cheap, cost is 10$/MW for all the hours
peakergen_cost=[50; 50; 50; 50];%peaker load generator is more expensive, 50$/MW for all the hours
discharge_cost=[0; 0; 0; 0]; %assuming no cost to discharge
charge_cost=[0; 0; 0; 0]; %assuming no cost to charge
dispatch = optimproblem;
ini_SOC=0;%battery initial State of charge is 0, empty.
soclevel = optimexpr(n,1);%optimization expression for soc level,since it's related to other variables.
charge_status = optimvar('charge_status',n,'Type','integer','LowerBound',0,'UpperBound',1); %charging status 0 /1
discharge_status=optimvar('discharge_status',n,'Type','integer','LowerBound',0,'UpperBound',1); %discharging status 0/1
charge = optimvar('charge',n,'LowerBound',0,'UpperBound',10); %charging MW,including limit;
discharge=optimvar('discharge',n,'LowerBound',0,'UpperBound',10); %discharging MW, including limits;
basegen = optimvar('basegen',n,'LowerBound',0,'UpperBound',400); %base load generator's output limits;
peakergen = optimvar('peakergen',n,'LowerBound',0,'UpperBound',200); %peaker generator's output limits
total_cost=sum(discharge_status.*discharge.*discharge_cost+basegen.*basegen_cost+peakergen.*peakergen_cost-charge_status.*charge.*charge_cost); %production cost
status=charge_status+discharge_status; %battery's status, could only be in one of the two status.
total_gen=discharge_status.*discharge-charge_status.*charge+basegen+peakergen; %total generation from the battery and the two generators.
which -all ones
whos
soclevel(1)=ini_SOC-discharge_status(1)*discharge(1)+charge_status(1)*charge(1) %SOC level at the end of the first hour
for i=2:4
soclevel(i)=soclevel(i-1)-discharge_status(i)*discharge(i)+charge_status(i)*charge(i); %SOC level for hour 2-4.
end
dispatch.Objective=total_cost; %objective is to minimize the production cost
dispatch.Constraints.powerbalance=total_gen==Load; %total generation equal to total load
dispatch.Constraints.bstatus=status==1; %battery status, charging and discharge mutual exclusive.
dispatch.Constraints.uppersoc=soclevel<=10; %SOC level upper limit;
dispatch.Constraints.lowersoc=soclevel>=0; %SOC level lower limit;
show(dispatch);

回答(1 个)

Walter Roberson
Walter Roberson 2022-3-14
THe problem is that ga() does not support the combination of integer constraints and nonlinear equality constraints. That is because the mechanism that ga() uses for integer constraints is to hook into the nonlinear constraints.
You can rewrite your code to eliminate discharge_status as being independent: it is just 1 minus charge_status.
But the power balance still remains, and Problem Based Optimization does not know how to construct the parameters for ga in a way that will work.
If you examine your powerbalance equation you will see that the charge or discharge status is multiplied by the charge or discharge -- you are selecting one or the other. But as far as ga is concerned, that means you are multiplying two inputs together... which is a nonlinear operation. So you cannot convert it to a linear inequality or equality.
The easiest way to handle this, for a modest number of indicator variables, is to iterate through all the possible combination of indicator variable values, invoking optimization for each one, recording all the results, and picking the best of them at the end.
%test economic disptach with 2 genertors and one battery
Load=[350; 607; 380; 605];%hourly load level, only study 4 hours
n = length(Load); %use load's demension to define the size
basegen_cost=[10; 10; 10; 10];%base load generator is cheap, cost is 10$/MW for all the hours
peakergen_cost=[50; 50; 50; 50];%peaker load generator is more expensive, 50$/MW for all the hours
discharge_cost=[0; 0; 0; 0]; %assuming no cost to discharge
charge_cost=[0; 0; 0; 0]; %assuming no cost to charge
dispatch = optimproblem;
ini_SOC=0;%battery initial State of charge is 0, empty.
soclevel = optimexpr(n,1);%optimization expression for soc level,since it's related to other variables.
charge_status = optimvar('charge_status',n,'Type','integer','LowerBound',0,'UpperBound',1); %charging status 0 /1
%discharge_status=optimvar('discharge_status',n,'Type','integer','LowerBound',0,'UpperBound',1); %discharging status 0/1
discharge_status = 1 - charge_status;
charge = optimvar('charge',n,'LowerBound',0,'UpperBound',10); %charging MW,including limit;
discharge=optimvar('discharge',n,'LowerBound',0,'UpperBound',10); %discharging MW, including limits;
basegen = optimvar('basegen',n,'LowerBound',0,'UpperBound',400); %base load generator's output limits;
peakergen = optimvar('peakergen',n,'LowerBound',0,'UpperBound',200); %peaker generator's output limits
total_cost=sum(discharge_status.*discharge.*discharge_cost+basegen.*basegen_cost+peakergen.*peakergen_cost-charge_status.*charge.*charge_cost); %production cost
total_gen=discharge_status.*discharge-charge_status.*charge+basegen+peakergen; %total generation from the battery and the two generators.
soclevel(1)=ini_SOC-discharge_status(1)*discharge(1)+charge_status(1)*charge(1); %SOC level at the end of the first hour
for i=2:4
soclevel(i)=soclevel(i-1)-discharge_status(i)*discharge(i)+charge_status(i)*charge(i); %SOC level for hour 2-4.
end
dispatch.Objective=total_cost; %objective is to minimize the production cost
dispatch.Constraints.powerbalance=total_gen==Load; %total generation equal to total load
dispatch.Constraints.uppersoc=soclevel<=10; %SOC level upper limit;
dispatch.Constraints.lowersoc=soclevel>=0; %SOC level lower limit;
show(dispatch);
OptimizationProblem : Solve for: basegen, charge, charge_status, discharge, peakergen where: charge_status integer minimize : 10*basegen(1) + 10*basegen(2) + 10*basegen(3) + 10*basegen(4) + 50*peakergen(1) + 50*peakergen(2) + 50*peakergen(3) + 50*peakergen(4) subject to powerbalance: (((((1 - charge_status) .* discharge) - (charge_status .* charge)) + basegen) + peakergen) == extraParams{1} extraParams{1}: 350 607 380 605 subject to uppersoc: arg_LHS <= arg_RHS where: arg1 = zeros(4, 1); arg3 = (1 - charge_status); arg1(1) = ((-(arg3(1) .* discharge(1))) + (charge_status(1) .* charge(1))); arg8 = (1 - charge_status); arg14 = (1 - charge_status); arg18 = (charge_status(2) .* charge(2)); arg1(2) = ((((-(arg8(1) .* discharge(1))) + (charge_status(1) .* charge(1))) - (arg14(2) .* discharge(2))) + arg18); arg20 = (1 - charge_status); arg26 = (1 - charge_status); arg30 = (charge_status(2) .* charge(2)); arg33 = (1 - charge_status); arg35 = (arg33(3) .* discharge(3)); arg38 = (((((-(arg20(1) .* discharge(1))) + (charge_status(1) .* charge(1))) - (arg26(2) .* discharge(2))) + arg30) - arg35); arg1(3) = (arg38 + (charge_status(3) .* charge(3))); arg40 = (1 - charge_status); arg46 = (1 - charge_status); arg50 = (charge_status(2) .* charge(2)); arg53 = (1 - charge_status); arg55 = (arg53(3) .* discharge(3)); arg58 = (((((-(arg40(1) .* discharge(1))) + (charge_status(1) .* charge(1))) - (arg46(2) .* discharge(2))) + arg50) - arg55); arg61 = (1 - charge_status); arg1(4) = (((arg58 + (charge_status(3) .* charge(3))) - (arg61(4) .* discharge(4))) + (charge_status(4) .* charge(4))); arg_LHS = arg1(:); arg2 = 10; arg1 = arg2(ones(1,4)); arg_RHS = arg1(:); subject to lowersoc: arg_LHS >= zeros(4, 1) where: arg1 = zeros(4, 1); arg3 = (1 - charge_status); arg1(1) = ((-(arg3(1) .* discharge(1))) + (charge_status(1) .* charge(1))); arg8 = (1 - charge_status); arg14 = (1 - charge_status); arg18 = (charge_status(2) .* charge(2)); arg1(2) = ((((-(arg8(1) .* discharge(1))) + (charge_status(1) .* charge(1))) - (arg14(2) .* discharge(2))) + arg18); arg20 = (1 - charge_status); arg26 = (1 - charge_status); arg30 = (charge_status(2) .* charge(2)); arg33 = (1 - charge_status); arg35 = (arg33(3) .* discharge(3)); arg38 = (((((-(arg20(1) .* discharge(1))) + (charge_status(1) .* charge(1))) - (arg26(2) .* discharge(2))) + arg30) - arg35); arg1(3) = (arg38 + (charge_status(3) .* charge(3))); arg40 = (1 - charge_status); arg46 = (1 - charge_status); arg50 = (charge_status(2) .* charge(2)); arg53 = (1 - charge_status); arg55 = (arg53(3) .* discharge(3)); arg58 = (((((-(arg40(1) .* discharge(1))) + (charge_status(1) .* charge(1))) - (arg46(2) .* discharge(2))) + arg50) - arg55); arg61 = (1 - charge_status); arg1(4) = (((arg58 + (charge_status(3) .* charge(3))) - (arg61(4) .* discharge(4))) + (charge_status(4) .* charge(4))); arg_LHS = arg1(:); variable bounds: 0 <= basegen(1) <= 400 0 <= basegen(2) <= 400 0 <= basegen(3) <= 400 0 <= basegen(4) <= 400 0 <= charge(1) <= 10 0 <= charge(2) <= 10 0 <= charge(3) <= 10 0 <= charge(4) <= 10 0 <= charge_status(1) <= 1 0 <= charge_status(2) <= 1 0 <= charge_status(3) <= 1 0 <= charge_status(4) <= 1 0 <= discharge(1) <= 10 0 <= discharge(2) <= 10 0 <= discharge(3) <= 10 0 <= discharge(4) <= 10 0 <= peakergen(1) <= 200 0 <= peakergen(2) <= 200 0 <= peakergen(3) <= 200 0 <= peakergen(4) <= 200
solution = solve(dispatch)
Solving problem using ga.
Error using optim.problemdef.OptimizationProblem/solve
GA does not solve problems with integer and equality constraints.
For more help see No Equality Constraints in the documentation.

类别

Help CenterFile Exchange 中查找有关 Quadratic Programming and Cone Programming 的更多信息

Community Treasure Hunt

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

Start Hunting!

Translated by