Find minimum consecutives in an optimvar

3 vues (au cours des 30 derniers jours)
Julian
Julian le 4 Août 2023
Modifié(e) : Julian le 11 Sep 2023
I try to "find" the minimum consecutives 0 or 1 in an integer optimvar.
Following a "normal logical" array, I would search for it as follows:
A = [0 0 0 1 1 0 0 1 0 1 1 1 0 0 0].';
% Find the position of the 1s
index = find(A);
% Calculate the difference between the zeros and find the indexes at wich a new block starts.
% A new Block starts at the first "index" and where the difference is bigger than 1
iStart = find([1; diff(index) >1]);
% The end of the block is always the index before the start of a new block
iEnd = [iStart(2:end)-1; size(index,1)];
% Calculate the length of the Blocks
onLength = iEnd-iStart+1;
offLength = ([index(iStart); length(A)+1] - [0; index(iEnd(1:end))] -1);
And I wanted to use this to "find" / define the minimum of a optimvar. But unfortunately this does not work, which is why I set the maximum like this:
% Define variables
prob = optimproblem;
n_max_off = 3;
N = 90;
ds_on = optimvar('ds_on', N, 'LowerBound',0, 'UpperBound', 1, 'Type','integer');
prob.Constraints.ds_max_off = optimconstr(N-n_max_off);
% The sum of the maximum +1 must be more the 1
% For more than the maximum, at least one element must be true.
for i = 1:N-n_max_off-1
prob.Constraints.ds_max_off(i) = sum(ds_on(i:i+n_max_off+1)) >= 1;
end
% Compressed code without loop
index = (0:n_max_off) + (1:N-n_max_off).';
prob.Constraints.ds_max_off(1:N-n_max_off) = sum(ds_on(index(1:N-n_max_off,:)),2) >= 1;
But to define the minimum I do not know how I can do it.
In other words:
I want to define a minimum and maximum length of zeros and ones which are my boundary conditions / constraints.
The maximum is not a problem, but to define the minimum length is my problem. So minimum and maximum length are my constraints.
My objective is someting different I left for readability.
  1 commentaire
Julian
Julian le 4 Sep 2023
I have found and already implemented a way to formulate the minimum number of a runtime linearly.
From the paper: "A computationally efficient mixed-integer linear formulation for the thermal unit commitment problem"
I plan to post the solution in the near future.

Connectez-vous pour commenter.

Réponse acceptée

Julian
Julian le 7 Sep 2023
Modifié(e) : Julian le 11 Sep 2023
The best solution is to formulate the minimum number of consecutives with a linear approach like in the paper: "A computationally efficient mixed-integer linear formulation for the thermal unit commitment problem" DOI: 10.1109/TPWRS.2006.876672
At first define the variable:
% Define variables
prob = optimproblem;
n_min_off = 4;
n_max_off = 10;
n_min_on = 2;
n_max_on = 3;
N = 90;
I use two optimvars:
ds_on = optimvar('ds_on', N, 'LowerBound',0, 'UpperBound', 1, 'Type','integer');
ds_start = optimvar('ds_start', N, 'LowerBound',0, 'UpperBound', 1, 'Type','integer');
The maximum of the consecutives is like I implemented it in the question:
% Compressed code without loop
index = (0:n_max_off) + (1:N-n_max_off).';
prob.Constraints.ds_max_off = sum(ds_on(index(1:N-n_max_off,:)),2) >= 1;
% the same for maximum on
%...
I search for the start but in the end I musst not forget to give "ds_start" a little weight in my minimization function:
prob.Constraints.ds_start = diff(ds_on) <= ds_start(2:end);
Afterwards I say, after "ds_start" is 1, the following "ds_on"s musst be on too:
for i = 2:N-n_min_on+1:
prob.Constraints.min_off(i) = ds_start(i) * n_min_on - sum(ds_on(i:i+n_min_on-1)) <= 0;
end
% of faster:
index = (1:n_min_on) + (1:N-n_min_on).';
prob.Constraints.min_on = ds_start(2:N-n_min_on+1) * n_min_on - sum(ds_on(index),2) <=0;
And it's very siilar for "min_off":
for i = n_min_off+1:N
prob.Constraints.min_off(i) = ds_start(i) * n_min_on + sum(ds_on(i-n_min_on:i-1)) <= n_min_on;
end
% or faster:
index = (0:n_min_off-1) + (1:N-n_min_off).';
prob.Constraints.min_off = ds_start(1:N-n_min_off) * n_min_off + sum(ds_on(index),2) <= n_min_off;
With this calculation I'm able to define a minimum on and off time for a appliance in an optimization.
I am also able to make it multidemensional if I have more appliances of this kind.
With this workaround it is also possible to have different kinds of "on" values.

Plus de réponses (1)

Matt J
Matt J le 4 Août 2023
Modifié(e) : Matt J le 4 Août 2023
It's going to be a nonlinear integer objective function, which means the solver it's going to choose is ga. You should save yourself the hassle and just implement the optimization with ga() directly.
  15 commentaires
Julian
Julian le 28 Août 2023
Modifié(e) : Julian le 28 Août 2023
I changed it to <= instead of == and it is calculating. I hope it will calculate faster, but I have still the question what kind of "problem" is better for Matlab to calculate?
Torsten
Torsten le 28 Août 2023
At least it's necessary to either remove integer variables or equality constraints from your code.

Connectez-vous pour commenter.

Produits


Version

R2023a

Community Treasure Hunt

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

Start Hunting!

Translated by