**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?

14 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

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

### 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 (한국어)