You are now following this question
- You will see updates in your followed content feed.
- You may receive emails, depending on your communication preferences.
how to do conditional statements using optimisation variables?
12 views (last 30 days)
Show older comments
hi all, how can i perform logical comparison using optimisation variable ?
I have tried this below code for optimisation using optimisation variable PbattV , but getting error :
Cost = Costa.*(PbattV<=200) +Costb.*(PbattV>=200);
P1= dt*Cost'*PbattV;
P2=dt*Cost'*PbattV;
P=P1-P2;
prob.ObjectiveSense = 'minimize';
prob.Objective = P;
An error occurred while running the simulation and the simulation was terminated Caused by: times Please help if you have any suggestion
basically i need to check if Pbatt is positive or negative and accordingly i have to chose Cost and use it for objective function;
1 Comment
Julian
on 21 Jul 2023
Hi NN, I wanted to ask If you have found a working solution for your problem?
Have you found a way to rewrite your Problem?
Accepted Answer
Walter Roberson
on 4 May 2021
Cost = Costa.*(PbattV<=200) +Costb.*(PbattV>=200);
Optimization variables cannot be converted to logical values. The only time you can compare an optimization variable to a value is in constructing a constraint.
Give up on trying to code it in terms of comparison operators: you will not succeed.
If there is a solution, then it will involve using mathematical tricks such as sqrt(x^2)/x to get the sign(x)
17 Comments
NN
on 18 Jul 2021
Is it possible to give if condition in objective function?
Obj function is maximising :
prob.Objective =dt*Price*Pnet - dt*Cost'*Ppv;
if Pnet is positive, it should be :
prob.Objective =dt*Price1*Pnet - dt*Cost'*Ppv;
If Pnet is negative ,it should be :
prob.Objective =dt*Price2*Pnet - dt*Cost'*Ppv;
Is it possible to give two equations like this and how does it calculate effective prob.objective ?
i have two prices to include depending on Pnet sign
Kindly advcie
Walter Roberson
on 18 Jul 2021
I have been finding it difficult to find ways to write it that will work for Pnet values that are close to 0.
If Pnet is an input, it would be much easier to run three versions of the code: one for positive Pnet, one for negative Pnet, and the third for Pnet being exactly 0.
Walter Roberson
on 18 Jul 2021
In that case, break the computation up into three pieces, one for negative, one for positive, and one for zero; and afterwards take the best out of the three.
NN
on 19 Jul 2021
In the below example,
one battery is considered and optimproblem has been defined for that.What if there are one more battery and is it possible to define two optimproblem like
prob=optimproblem;
prob1=optimproblem;
If so is this the correct format ?Please advice
NN
on 17 Aug 2021
if i need to break the computation into three pieces , like three functions seperately. how can i call those functions in optimization code ?Please advice as i am still stuck up with this problem.
Based on each function, which will check the sign of Pnet and load cost accordingly , then optimisation program should take values from those functions accordingly during the process.
NN
on 18 Aug 2021
Edited: Walter Roberson
on 18 Aug 2021
Please see the below code :It returns a value of zero ,and i am expecting and output of 500e3 for Pbattups. Please advice.
function [Pd,Pbattups,Ebattups] = battSolarOptimizetrial3(N,dt,Ppv,Pload,Einit,Cost,FinalWeight,upsbatteryMinMax)
prob = optimproblem;
% Decision variables
PdV = optimvar('PdV',N);
PbattupsV = optimvar('PbattupsV',N,'LowerBound',0,'UpperBound'500e3);
EbattupsV = optimvar('EbattupsV',N,'LowerBound',upsbatteryMinMax.Emin,'UpperBound',upsbatteryMinMax.Emax);
% Maximise the profit from the usage of battery and PV
prob.ObjectiveSense = 'minimize';
%prob.Objective = var1 -dt*DayaheadCost'*Ppv-FinalWeight*EbattupsV(N)-FinalWeight*Ebatt1V(N)-FinalWeight*Ebatt2V(N);
prob.Objective =dt*Cost'*PbattupsV- dt*Cost'*Ppv-FinalWeight*EbattupsV(N);
% Power input/output to battery
prob.Constraints.energyBalance = optimconstr(N);
prob.Constraints.energyBalance(1) = EbattupsV(1) == Einit;
prob.Constraints.energyBalance(2:N) = EbattupsV(2:N) == EbattupsV(1:N-1) - PbattupsV(1:N-1)*dt
% Satisfy power load with power from PV, grid and battery
prob.Constraints.loadBalance = Ppv + PdV + PbattupsV == Pload;
%prob.Constraints.battpower = PbattupsV<=500e3;
% Solve the linear program
options = optimoptions(prob.optimoptions,'Display','none');
[values,~,exitflag] = solve(prob,'Options',options);
% Parse optmization results
if exitflag <= 0
Pd = zeros(N,1);
Pbattups = zeros(N,1);
Ebattups = zeros(N,1);
else
Pd = values.PdV;
Pbattups = values.PbattupsV;
Ebattups = values.EbattupsV;
end
Walter Roberson
on 18 Aug 2021
PbattupsV = optimvar('PbattupsV',N,'LowerBound',0,'UpperBound'500e3);
^
missing operator between the option and the value. The code will not run.
I do not have the values for any of the variables you pass in, so I cannot run the code to test it.
NN
on 18 Aug 2021
Oh sorry, that is a typo error,
I have made changes to the example file given below the link .
Please see this file and advice
NN
on 18 Aug 2021
instead of conditional statements, can i call another function inside the function , so that it compares and returns the value(according to the sign).The comparison function is like written below
function [ Cost ] = Price( LBMPCost,Profit,Pbattups)
if Pbattups > 0
Cost=LMPCost;
elseif Pbattups < 0
Cost=DayaheadCost;
else
Cost= 0;
end
if so where and how do i call this function, so that in bjective function, it picks the cost as per the comparison and execute accordingly ?
Please advcie
NN
on 19 Aug 2021
Sir, please see this link, i have posted it in detail.
https://www.mathworks.com/matlabcentral/answers/1436322-battery-storage-optimisation-problem_charge-and-discharge-conditional-constraint-nested-function_jn
Walter Roberson
on 19 Aug 2021
No, that is not possible. It will never be possible.
MATLAB does not currently support sign() of an optimization variable. That is a product limitation in current releases. I am not aware of any reason sign() could not be implemented in future -- it might take work, but I think it could be done -- it is not too different in some ways from supporting PbattupsV^2/PbattupsV (which is abs(PbattupsV) except when PbattupsV == 0)
The way that setting up a Problem Based Optimization works is that creating Optimization Variables creates variables of a special class, and arithmetic operations (and related operations) on variables of the class record a "history" of which operations were requested to be undertaken, but without computing the actual value at that point. When you finally call solve(), the optimizer analyzes the history of the operations on the objects and effectively generates code and data structures that, given numeric parameters, would undertake those operations; and then it asks one of the optimization functions such as fmincon to execute the generated code with the generated data (such as a generated an Aeq and beq matrix.) Problem based optimization does not extend the reach of what kind of optimization can be done: Problem based optimization is a way to make it easier for people to create advanced systems with it generating calls to the existing optimization functions automatically.
When you are creating a Problem Based Optimization, it is possible to code as-if you were calling a user-defined function. And what happens when you do that is that the user-defined function is called with the Optimization Variables passed in, and just like before the history of the requested mathematical operations is recorded. The function is not going to be actually be called with numeric parameters: MATLAB is instead going to effectively be extracting the formula that is implemented by the function.
Think of the system as having a number of similarities with using the Symbolic Toolbox passing in symbolic variables: you can easily have done
syms x
y = my_function(x)
y =
y =
function y = my_function(x)
y = x^2/(cos(x)+sin(x))
end
and when you do, each step of the way the Symbolic Toolbox is pretty much recording a history of the requested actions; in this example, my_function is not going to be invoked with a numeric x, it is only going to be called with a symbolic x, and that leaves a record of the requested computations and that record is the result of calling the function; the result is not to calculate the value on a particular numeric x.
So, with Optimization Variables, you can invoke your own function. That in itself is not a problem. However, just like in your main line of code, what you do with the variables inside the function is restricted to the operations where MATLAB knows how to record a history of computation, and is not being asked to make any decisions based upon particular input values.
Now you propose
function [ Cost ] = Price( LBMPCost,Profit,Pbattups)
if Pbattups > 0
where Pbattups is an optimization variable. Can this be handled just by consulting the record of requested computations that is in Pbattups ? NO -- or at least not usually. For example if the lower bound for Pbattups were 100 then hypothetically MATLAB could prove that Pbattups > 0 would always be true... but not generally. But the if statement requires that the computation (Pbattups > 0) be decidable to a single logical true or false in order for MATLAB to be able to know whether to execute the body of the if or not. The optimization system is not able to process that if / elseif into some kind of conditional construct that at some point in the future when actual numeric values are available would do the requested operation.
... And remember that Pbattups is a vector of N variables. Should, hypothetically, the history of computation be recorded as requiring a test that all elements of Pbattups are greater than 0, or should it be proceeding on an element-by-element basis, doing the main body for the parts of Pbattups that are greater than 0, doing the elseif for the parts of Pbattups that are not greater than 0 but are less than 0, and so on ? Sure, possibly maybe it would be possible to build in constructs that could deal with recording a history of conditional computation... but it is never going to happen based upon automatic conversion of if / elseif constructs. It would be a different construct... something similar to the Symbolic Toolbox piecewise() operation.
Earlier I wrote that I think sign() could be implemented in the future. But it would not be simple -- for the same reason that abs() would not be simple, and the same reason that piecewise() would not be simple:
The difficulty is that the mathematics used by all of the supported optimizers, requires that the expressions be differentiatable. Problem-Based Optimization automatically attempts to find derivatives, in order build the gradient. But... abs() and sign() and piecewise() do not have continuous derivatives. So although I say that I think that the optimizers could be extended to handle sign(), it would be a fair amount of work, as the optimizers would have to be rewritten in order to handle discontinuous derivatives.
To recap:
Problem Based Optimization is never going to handle if or elseif . And if it is ever extended to handle sign() then it is going to require a fair bit of work for Mathworks.
NN
on 19 Aug 2021
Thank you so much for the detailed explanation.
i will try to find anther approach to my problem.
Much thanks for your time and effort .
Walter Roberson
on 19 Aug 2021
Earlier I suggested using three versions of the code, one for negative, one for positive, one for zero.
At the time I made that suggestion, I was thinking in terms of there being a single scalar variable that you would need to test.
If instead you need to test N different variables, like your optimvar('PbattupsV',N,'LowerBound',0,'UpperBound',500e3); then you would need different runs rather than 3 different runs, unless you were able to reduce the number by finding some cases in which two entries would have to have the same sign.
NN
on 19 Aug 2021
Ok.Still when it doesnt support another function with conditional statements, or even constraints, i cant perform that operation.
I am thinking some other approach without considering sign change
Walter Roberson
on 21 Aug 2021
When you have discontinuous derivatives, the alternative supported by MATLAB are:
- ga()
- patternsearch()
- particleswarm()
- surrogateopt() https://www.mathworks.com/help/gads/surrogateopt.html
- simulannealbnd() https://www.mathworks.com/help/gads/simulannealbnd.html
More Answers (0)
See Also
Categories
Find more on Get Started with Optimization Toolbox in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!An Error Occurred
Unable to complete the action because of changes made to the page. Reload the page to see its updated state.
Select a Web Site
Choose a web site to get translated content where available and see local events and offers. Based on your location, we recommend that you select: .
You can also select a web site from the following list
How to Get Best Site Performance
Select the China site (in Chinese or English) for best site performance. Other MathWorks country sites are not optimized for visits from your location.
Americas
- América Latina (Español)
- Canada (English)
- United States (English)
Europe
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom(English)
Asia Pacific
- Australia (English)
- India (English)
- New Zealand (English)
- 中国
- 日本Japanese (日本語)
- 한국Korean (한국어)