How to implement shutdown, start-up, ramp-up and ramp-down in a MILP if capacity is optimized as well and minimum power exists - optimization

I am currently trying to solve a problem with Mixed-Integer linear problems. I have a component, which capacity and operation I want to optimize. This component has a lower limit of operation, p_low. The optimization can either run the component between its upper limit (the capacity) or p_low, but it should also be able to shut-down the component.
Here starts the issue: I have no idea how to implement both possibilities, as a shut-down would violate the minimal power constraint.
I thought about using binary variables for decision (b_status), but I have a problem with the the capacity of the component, because it is optimized as well and combining the capacity variable with the binary variable:
p >= p_low * capacity * b_status -> if b_status is 0 -> p >= 0; else: p >= p_low * capacity
... would result in a non-linear problem as the combination of capacity and b_status is not allowed in linear models (both variables).
Does someone know a way to implement this? I know this is not the main topic here, but it might be worth the try asking.

You are almost there...
You are correct, you will need 2 variables to model this equipment. Let:
x_on = {0, 1} a binary variable to indicate whether system is on/off
x_load = {x: x >= 0 } a continuous, non-negative variable to indicate the current load
Then you will need to creatively use x_on as an indicator variable within the constraints to either set x_load at zero or between the low-high limits...
High constraint: x_load <= x_on * high_limit
Low constraint: x_load >= x_on * low_limit
Those are linear. Plug in some values to ensure you believe them. :). Presumably somewhere in your model you are minimizing x_load and this will get it done.
=================
Edit for variable capacity
I misread your problem. Per your comment, I think you are again on the right track and using a big-M constraint can do this.
In addition to the above variables x_on and x_load let
C = {x : x >=0} a continuous non-negative variable to represent the capacity of the machine
M = any reasonable upper bound on C
You have a workable solution for the low limit. By using 2 constraints for the high (3 constraints total), you can incorp the big-M for the high also
Low: x_load >= low_lim * C - M * (1 - x_on)
High: x_load <= C
Off: x_load <= M * x_on

Related

In AMPL, how to refer to part of the result, and use them in multiple places

I'm learning AMPL to speed up a model currently in excel spreadsheet with excel solver. It basically based on the matrix multiplication result of a 1 x m variables and an m x n parameters. And it would find the variables to maximize the minimum of certain values in the result while keeping some other values in the same result satisfying a few constraints. How to do so in AMPL?
Given: P= m x n parameters
Variable: X= 1 x m variable we tried to solve
Calculate: R= X x P , result of matrix multiplication of X and P
Maximize: min(R[1..3]), the minimum value of the first 3 values in the result
Subject to: R[2]<R[4]
min(R[6..8])>20
R[5]-20>R[7]
X are all integers
I read several tutorials and look up the manual but can't find the solution to this seemingly straightforward problem. All I found is maximize a single value, which is the calculation result. And it was used only once and does not appear again in the constraint.
The usual approach for "maximize the minimum" problems in products like AMPL is to define an auxiliary variable and set linear constraints that effectively define it as the minimum, converting a nonlinear function (min) into linear rules.
For instance, suppose I have a bunch of decision variables x[i] with i ranging over an index set S, and I want to maximize the minimum over x[i]. AMPL syntax for that would be:
var x_min;
s.t. DefineMinimum{i in S}: x_min <= x[i];
maximize ObjectiveFunction: x_min;
The constraint only requires that x_min be less than or equal to the minimum of x[i]. However, since you're trying to maximize x_min and there are no other constraints on it, it should always end up exactly equal to that minimum (give or take machine-arithmetic epsilon considerations).
If you have parameters (i.e. values are known before you run the optimisation) and want to refer to their minimum, AMPL lets you do that more directly:
param p_min := min{j in IndexSet_P} p[j];
While AMPL also supports this syntax for variables, not all of the solvers used with AMPL are capable of accepting this type of constraint. For instance:
reset;
option solver gecode;
set S := {1,2,3};
var x{S} integer;
var x_min = min{s in S} x[s];
minimize OF: sum{s in S} x[s];
s.t. c1: x_min >= 5;
solve;
This will run and do what you'd expect it to do, because Gecode is programmed to recognise and deal with min-type constraints. However, if you switch the solver option to gurobi or cplex it will fail, since these only accept linear or quadratic constraints. To apply a minimum constraint with those solvers, you need to use something like the linearization trick I discussed above.

Linear Programming: Purely linear formulation (LP) for the expression "if x > 0; y =0 / if y > 0; x=0" without binary variables

I have a problem which often occurs in energy system modelling (modelling of storages) where charging of a storage system is not allowed to when it is discharging and vice versa.
Let x and y be continous positive decision variables that represent the charging/discharging power of the storage unit. Now I am trying to express the following logic in equations or inequalities:
if x > 0:
y = 0
if y > 0:
x = 0
I know this can be realized with binary variables via the following equations if b is a binary variable and x_ub and y_ub represent the respective upper bound of the variables:
x <= b * x_ub
y <= (1-b) * y_ub
This results in a mixed-integer linear programm (MILP) and of course induces all the properties of a MILP which lay in higher runtimes, other interpretations of the solution, ...
Another way to get a pure LP formulation is to work with (very low) costs that are attached to x and y so that only one of both variables is set to a positive value. But this also affects my objective, has other disadvantages as is is somewhat of a hotfix.
So here's my question: Is there any way to express the logic above (if/else) in a purely linear program (LP)?
Thanks in advance!

how to calculate gain of a controller for desired bandwidth?

I have been designing a controller for a motion system. The controller contains a gain, Proportional integrator(PI) and a lead filter in series. I have tuned the gain of the controller manually to obtain a desired bandwidth(cross over frequency). The frequency of lead and PI are based on rule of thumb(for lead, bandwidth/3 in the numerator, bandwidth*3 in the denominator and for integrator its bandwidth/5).
How can I decide on the gain of the controller to obtain automatically just by mentioning desired bandwidth. Is there any rule of thumb to be followed? How does it change according to sampling frequency?
PID controller design is an inherently difficult problem. You can't do it via simple matters unless your system allows you to derive certain expressions due to simplicity.
One way to do it is to resort back to nonconvex nonsmooth optimization algorithms such as Matlab's own systune or HIFOO or some other tools that solve for "a" solution but not "the" solution.
There are examples for loop shaping and bandwidth constraints on the documentation.
Well you could simply use your rules of thumb regarding for the I action and the lead filter. Then you simply check the bode diagram of the open-loop. Check the magnitude of the system at the frequency where you want your bandwidth. Then you can simply calculate how much gain you need to apply to move the point upwards to 0 dB, the bandwidth.
Furthermore, the rules of thumb assume a high enough sampling frequency. But, in general, if the sampling frequency becomes lower your gain also will be lower, however the frequencies of the I action and the lead filter will also change.
-edit-
I made a small script for you. The script is self explaining.
The same methods can be applied in the discrete domain. Furthermore, I would not design the controller in discrete domain, but rather in continuous time-domain. Following, I would use a discretization method to convert the controller from continuous time to discrete time, such as the Bilinear transform. http://nl.mathworks.com/help/control/ref/c2d.html provides information how you can do this in Matlab.
In addition, I would like to recommend this tool for you, http://cstwiki.wtb.tue.nl/index.php?title=Home_of_ShapeIt
clear all;
close all;
clc;
%% Initialize parameters
s = tf('s');
% Mass of plant
m = 10;
% Desired bandwidth
BW = 10;
%% Define plant
P = 1/(m*s^2);
%% Define filters
% Lead lag filter
f1 = (1/(2*pi*BW/3)*s + 1)/(1/(2*pi*BW*3)*s + 1);
% Integrator
f2 = (s + 2*pi*BW/5)/s;
% define Controller
C = f1*f2;
%% Determine gain
% Open loop
OL = C*P;
% Evaluate at bandwidth and get magnitude
mag = abs(evalfr(OL,2*pi*BW));
% Desired gain is 1/mag
C = 1/mag*C;
% Recalculate open loop
OL = C*P;
% Evaluate at bandwidth, magnitude should be 1
sprintf('Magnitude at bandwidth: %f\n',abs(evalfr(OL,2*pi*BW)));
%% Compute other stuff
% Sensnitivity
SS = 1/(1 + OL);
% Closed loop, complementary sensitivity
CL = OL*SS;
% Process sensitivity
PS = P*SS;
% Controller sensitivity
CS = C*SS;
%% Create some plots
% Open loop
figure(1);
bode(OL);
title('Open loop');
% Nyquist
figure(2);
nyquist(OL);
% Other sensitivities
figure(3);
subplot(2,2,1);
bodemag(CL);
title('Closed loop');
subplot(2,2,2);
bodemag(SS);
title('Sensitivity');
subplot(2,2,3);
bodemag(PS);
title('Process sensitivity');
subplot(2,2,4);
bodemag(CS);
title('Controller sensitivity');
% Step
figure(4);
step(CL);
title('Step response');

fmincon : impose vector greater than zero constraint

How do you impose a constraint that all values in a vector you are trying to optimize for are greater than zero, using fmincon()?
According to the documentation, I need some parameters A and b, where A*x ≤ b, but I think if I make A a vector of -1's and b 0, then I will have optimized for the sum of x>0, instead of each value of x greater than 0.
Just in case you need it, here is my code. I am trying to optimize over a vector (x) such that the (componentwise) product of x and a matrix (called multiplierMatrix) makes a matrix for which the sum of the columns is x.
function [sse] = myfun(x) % this is a nested function
bigMatrix = repmat(x,1,120) .* multiplierMatrix;
answer = sum(bigMatrix,1)';
sse = sum((expectedAnswer - answer).^2);
end
xGuess = ones(1:120,1);
[sse xVals] = fmincon(#myfun,xGuess,???);
Let me know if I need to explain my problem better. Thanks for your help in advance!
You can use the lower bound:
xGuess = ones(120,1);
lb = zeros(120,1);
[sse xVals] = fmincon(#myfun,xGuess, [],[],[],[], lb);
note that xVals and sse should probably be swapped (if their name means anything).
The lower bound lb means that elements in your decision variable x will never fall below the corresponding element in lb, which is what you are after here.
The empties ([]) indicate you're not using linear constraints (e.g., A,b, Aeq,beq), only the lower bounds lb.
Some advice: fmincon is a pretty advanced function. You'd better memorize the documentation on it, and play with it for a few hours, using many different example problems.

Efficiency of the modulo operator for bounds checking

I was reading this page on operation performance in .NET and saw there's a really huge difference between the division operation and the rest.
Then, the modulo operator is slow, but how much with respect to the cost of a conditional block we can use for the same purpose?
Let's assume we have a positive number y that can't be >= 20. Which one is more efficient as a general rule (not only in .NET)?
This:
x = y % 10
or this:
x = y
if (x >= 10)
{
x -= 10
}
How many times are you calling the modulo operation? If it's in some tight inner loop that's getting called many times a second, maybe you should look at other ways of preventing array overflow. If it's being called < (say) 10,000 times, I wouldn't worry about it.
As for performance between your snippets - test them (with some real-world data if possible). You don't know what the compiler/JITer and CPU are doing under the hood. The % could be getting optimized to an & if the 2nd argument is constant and a power of 2. At the CPU level you're talking about the difference between division and branch prediction, which is going to depend on the rest of your code.