Hi I am working with the brute force method to examine possible combinations of "panels" and "turbines"
My code is
for number_panels = 0:5
for number_turbines = 0:10
for n = 1:24 % number of hours per day
deficit(n) = Demand(n) - (PV_supply(n)*number_panels) -...
(WT_supply(n)*number_turbines);% hourly power deficit
if deficit(n)<0
deficit(n) = 0;
end
The problem I have above is that I haven't yet figured the correct indexing of this code.
What I am trying to do is find the "deficit" for the "number_panels" , "number_turbines" and "n". As it stands I can only find the "deficit" for the last for loop.
How can I code so that I can have the option to access the nth row (or sets of "n" i.e 1-24) and also for the "number_panels" "number_turbines" option?
thanks - in order to find the sum of each deficit(n) value and thus have the respective total deficit of the 24 hour period I have done the following which seems to me to be able to do what I am asking but I am getting incorrect answers:
daily_deficit(number_panels + 1, number_turbines + 1) =...
sum(deficit(number_panels + 1, number_turbines + 1,n)) –
function calcDeficit.m:
File Edit Options Buffers Tools ObjC Help
function deficit = calcDeficit (Demand, PV_supply, WT_supply)
% initialize the size (good practice)
deficit = zeros(6,11,24);
for number_panels = 0:5
for number_turbines = 0:10
for n = 1:24 % number of hours per day
deficit(number_panels+1,number_turbines+1,:) = Demand(n) - (PV_supply(n)*number_panels) -...
(WT_supply(n)*number_turbines);% hourly power deficit
if deficit(n)<0
deficit(n) = 0;
end
end
end
end
return
example call:
Demand=randn(24,1); PV_supply=randn(24,1); WT_supply=randn(24,1); test(Demand,PV_supply,WT_supply)
You access Demand by
Demand(panels+1,number_turbines+1,hour)
Your problem is that you're storing the deficit result as a function only of the value n, the number of hours per day. In your inner loop around n, you keep replacing the values each time through your outer loops, so at the end of the run, you only have the value for n = 1:24 at number_panels = 5 and number_turbines = 10.
Try this:
deficit(number_panels+1, number_turbines+1, n) = ...
That way at the end, you can check any combination given the three indices. I've added a value of 1 to number_panels and number_turbines because MATLAB uses 1-based indexes. To get your results for a specific number of panels or turbines, make sure to add 1 when checking.
Specifically, for 3 panels and 4 turbines at hour 5 in the day:
disp(deficit(3+1, 4+1, 5))
EDIT: Added 1 to the values of number_panels and number_turbines to avoid 0-indexing.
Related
I'm trying to calculate the DT value from a model I set up on Sim4Life. Firstly, i'd like to say that I am a complete beginner and I am trying to understand how programming works in general.
Now, I have a function with some constants and two variables, the one being time Dt (starting from 1 sec to 900 secs) and the other being the initial DT_i value. I want to calculate the increase of temperature for every second and create a loop that replaces the DT_i value with the DT_1_i value and also calculates the increased temperature DT_i_1. The function looks like this: DT_1_i=DT_i+Dt.
I know it is a very simple problem but I couldn't work my way through other similar questions. Any help would be appreciated.
Temperature variation:
You need initial temperature variation , I used 0
T(i+1) stands for Next temperature variation
T(i) stands for present temperature variation
i stands for time step, dt
Read through comment in my code
Time
Use for loop to set the time for i = 1 : 900 %Temperature increase end
i =1:900 just means
first run use time = 1s,
second run time = 1+1 = 2
so on till 900
The code is as follow
% Initial Temperature variation is set to zero, unless you have some data
d = 1.3;
c = 3.7;
S_i = 3*10^3;
t_reg = 900;
%Time
t = 1:900;
% Length oftime to help me know the size of the variable needed to
% initialize
l = length(t);
% Initialize variable that used to store DT it helps speed up
% comutation
% Initial Temperature variation is set to zero, unless you have some data
DT = zeros(1, l);
for i = 1:900
% the value of i represent dt, first run i = 1, dt = 1, second run
% i = 2 and dt = 2 so on
if i == 900
%do nothing already reached the last index 900, i+1 = 901 will be
%out of range
else
DT(i+1) = DT(i) + (i./t_reg).*(d.*sqrt(c*S_i)-DT(i+1));
end
end
Hello everyone I have a new small problem:
The data I am using have a weird trade time that goes from 17.00 of one day to 16.15 of the day after.
That means that, e.g., for the day 09-27-2013 The source I am using registers the transactions occurred as follows:
DATE , TIME , PRICE
09/27/2013,17:19:42,3225.00,1 #%first obs of the vector
09/27/2013,18:37:59,3225.00,1 #%second obs of the vector
09/27/2013,08:31:32,3200.00,1
09/27/2013,08:36:17,3203.00,1
09/27/2013,09:21:34,3210.50,1 #%fifth obs of the vector
Now first and second obs are incorrect for me: they belong to 9/27 trading day but they have been executed on 9/26. Since I am working on some functions in matlab that relies on non-decremental times I need to solve this issue. The date format I am using is actually the datenum Matlab format so I am trying to solve the problem just subtracting one from the incorrect observations:
%#Call time the time vector, I can identify the 'incorrect' observations
idx=find(diff(time)<0);
time(idx)=time(idx)-1;
It is easy to tell that this will only fix the 'last' incorrect observations of a series. In the previous example this would only correct the second element. And I should run the code several times (I thought about a while loop) until idx will be empty. This is not a big issue when working with small series but I have up to 20millions observations and probably hundred of thousands consecutively incorrect ones.
Is there a way to fix this in a vectorized way?
idx=find(diff(time)<0);
while idx
However, given that the computation would not be so complex I thought that a for loop could efficiently solve the issue and my idea was the following:
[N]=size(time,1);
for i=N:-1:1
if diff(time(i,:)<0)
time(i,:)=time(i,:)-1;
end
end
sadly it does not seems to work.
Here is an example of data I am actually using.
735504.591157407
735507.708030093 %# I made this up to give you an example of two consecutively wrong observations
735507.708564815 %# This is an incorrect observation
735507.160138889
735507.185358796
735507.356562500
Thanks everyone in advance
Sensible version -
for count = 1:numel(time)
dtime = diff([0 ;time]);
ind1 = find(dtime<0,1,'last')-1;
time(ind1) = time(ind1)-1;
end
Faster-but-crazier version -
dtime = diff([0 ;time]);
for count = 1:numel(time)
ind1 = find(dtime<0,1,'last')-1;
time(ind1) = time(ind1)-1;
dtime(ind1+1) = 0;
dtime(ind1) = dtime(ind1)-1;
end
More Crazier version -
dtime = diff([0 ;time]);
ind1 = numel(dtime);
for count = 1:numel(time)
ind1 = find(dtime(1:ind1)<0,1,'last')-1;
time(ind1) = time(ind1)-1;
dtime(ind1) = dtime(ind1)-1;
end
Some average computation runtimes for these versions with various datasizes -
Datasize 1: 3432 elements
Version 1 - 0.069 sec
Version 2 - 0.042 sec
Version 3 - 0.034 sec
Datasize 2: 20 Million elements
Version 1 - 37029 sec
Version 2 - 23303 sec
Version 3 - 20040 sec
So apparently I had 3 other different problems in the data source that I think could have stucked the routine Divakar proposed. Anyway I thought it was being too slow so I started thinking to another solution and came up with a super quick vectorized one.
Given that the observations I wanted to modify fall in a determined known interval of time the function just look for every observation falling in that interval and modifies it as I want (-1 in my case).
function [ datetime ] = correct_date( datetime,starttime, endtime)
%#datetime is my vector of dates and times in matlab numerical format
%#starttime is the starting hour of the interval expressed in datestr format. e.g. '17:00:00'
%#endtime is the ending hour of the interval expressed in datestr format. e.g. '23:59:59'
if (nargin < 1) || (nargin > 3),
error('Requires 1 to 3 input arguments.')
end
% default values
if nargin == 1,
starttime='17:00';
endtime='23:59:59';
elseif nargin == 2,
endtime='23:59:59';
end
tvec=[datenum(starttime) datenum(endtime)];
tvec=tvec-floor(tvec); %#As I am working on multiples days I need to isolate only HH:MM:SS for my interval limits
temp=datetime-floor(datetime); %#same motivation as in the previous line
idx=find(temp>=tvec(1)&temp<=tvec(2)); %#logical find the indices
datetime(idx)=datetime(idx)-1; %#modify them as I want
clear tvec temp idx
end
So I have a list of 190 numbers ranging from 1:19 (each number is repeated 10 times) that I need to sample 10 at a time. Within each sample of 10, I don't want the numbers to repeat, I tried incorporating a while loop, but computation time was way too long. So far I'm at the point where I can generate the numbers and see if there are repetitions within each subset. Any ideas?
N=[];
for i=1:10
N=[N randperm(19)];
end
B=[];
for j=1:10
if length(unique(N(j*10-9:j*10)))<10
B=[B 1];
end
end
sum(B)
Below is an updated version of the code. this might be a little more clear in showing what I want. (19 targets taken 10 at a time without repetition until all 19 targets have been repeated 10 times)
nTargs = 19;
pairs = nchoosek(1:nTargs, 10);
nPairs = size(pairs, 1);
order = randperm(nPairs);
values=randsample(order,19);
targs=pairs(values,:);
Alltargs=false;
while ~Alltargs
targs=pairs(randsample(order,19),:);
B=[];
for i=1:19
G=length(find(targs==i))==10;
B=[B G];
end
if sum(B)==19
Alltargs=true;
end
end
Here are some very simple steps to do this, basically you just shuffle the vector once, and then you grab the last 10 unique values:
v = repmat(1:19,1,10);
v = v(randperm(numel(v)));
[a idx]=unique(v);
result = unique(v);
v(idx)=[];
The algorithm should be fairly efficient, if you want to do the next 10, just run the last part again and combine the results into a totalResult
You want to sample the numbers 1:19 randomly in blocks of 10 without repetitions. The Matlab function 'randsample' has an optional 'replacement' argument which you can set to 'false' if you do not want repetitions. For example:
N = [];
replacement = false;
for i = 1:19
N = [N randsample(19,10,replacement)];
end
This generates a 19 x 10 matrix of random integers in the range [1,..,19] without repetitions within each column.
Edit: Here is a solution that addresses the requirement that each of the integers [1,..,19] occurs exactly 10 times, in addition to no repetition within each column / sample:
nRange = 19; nRep = 10;
valueRep = true; % true while there are repetitions
nLoops = 0; % count the number of iterations
while valueRep
l = zeros(1,nRep);
v = [];
for m = 1:nRep
v = [v, randperm(nRange,nRange)];
end
m1 = reshape(v,nRep,nRange);
for n = 1:nRep
l(n) = length(unique(m1(:,n)));
end
if all(l == nRep)
valueRep = false;
end
nLoops = nLoops + 1;
end
result = m1;
For the parameters in the question it takes about 300 iterations to find a result.
I think you should approach this constructively.
It's easy to initially find a 19 groups that fulfill your conditions just by rearranging the series 1:19: series1 = repmat(1:19,1,10); and rearranged= reshape(series1,10,19)
then shuffle the values
I would select two random columns copy them and switch the values at two random positions
then make a test if it fulfills your condition - like: test = #(x) numel(unique(x))==10 - if yes replace your columns
just keep shuffling till your time runs out or you are happy
of course you might come up with more efficient shuffling or testing
I was given another solution through the MATLAB forum that works pretty well (Credit to Niklas Nylen over on the MATLAB forum). Computation time is pretty low too. It basically shuffles the numbers until there are no repetitions within every 10 values. Thanks all for your help.
y = repmat(1:19,1,10);
% Run enough iterations to get the output random enough, I selected 100000
for ii = 1:100000
% Select random index
index = randi(length(y)-1);
% Check if it is allowed to switch places
if y(index)~=y(min(index+10, length(y))) && y(index+1)~=y(max(1,index-9))
% Make the switch
yTmp = y(index);
y(index)=y(index+1);
y(index+1)=yTmp;
end
end
I want to make the code below fast. It takes so long time to run, and I got this error:
Warning: FOR loop index is too large. Truncating to 2147483647.
I need to calculate over 3^100 so... is it impossible?
function sodiv = divisorSum(n)
sodiv = 0;
for i=1:n
if (mod(n,i) == 0)
sodiv = sodiv + i;
end
end
end
function finalSum1 = formular1(N,n)
finalSum1 = 0;
for k = 1:N
finalSum1 = finalSum1 + (divisorSum(k) * divisorSum(3^n*(N-k)));
end
end
Nv=100;
nv=[1:20];
for i=1:length(nv)
tic;
nfunc1(i)=formular1(Nv,nv(i));
nt1(i)=toc;
sprintf('nt1 : %d finished, %f', i,nt1(i))
end
The purpose of this code is to check the algorithm's calculation time.
The algorithm is too general and inefficient for this particular problem.
I understand you want to sum the divisors of 3^100. But these divisors are easily determined.
S = 1 + 3 + 3^2 + 3^3 + ... + 3^100, a geometric series.
3*S = 3 + 3^2 + ... + 3^101
subtract
2*S = 3^101 - 1
S = (3^101 - 1)/2
This code will never finish, because it is so inefficient.
For instance, there is a function that counts number of all divisors and is going through all numbers from 1 to N and count. But using an efficient formula would make it run much master.
Let's say that one need to sum divisors of number a^b where a is prime number.
Instead of calculating a^b and going form 1 to a^b, one can see that it is better going
a^1, a^2, a^3, ..., a^n, because only these numbers are divisors. But you can go even further and observe that the sum of these numbers are the sum of geometric progression so the number of divisors become:
sum divisors, a^b = (a^(b+1)-1) / (a-1)
I have made the following changes to the code but still get the "Index exceeds matrix dimensions" error on the line where the "if statement" is called and I am for looping the "h" starting from 2:25. I still have net figured out how I can use an element from the previous dimension in the current dimension equation expression
number_of_days = 3;
number_of_hours = 24*number_of_days;
number_panels = 1:5;
for idx_number_panels = 1:length(number_panels) % range of PV panel units examined
for number_turbines = 0:1 % range of wind turbine units examined
for number_batteries = 1:2 % range of battery units examined
for h=2:25 %# hours
battery_capacity(:,:,:,1,1) = max_battery_capacity*number_batteries;
for d = 1:number_of_days %# which day
n = h + 24*(d-1);
if (max_battery_capacity*number_batteries) - (battery_capacity(idx_number_panels, number_turbines+1 ,number_batteries, h-1,d)*number_batteries) >0
storage_availability(idx_number_panels, number_turbines+1 ,number_batteries, h,d) = (max_battery_capacity*number_batteries) - (battery_capacity(idx_number_panels, number_turbines+1 ,number_batteries, h-1,d)) ;
else
storage_availability(idx_number_panels, number_turbines+1 ,number_batteries, h,d) = 0;
end
Let's look at this just by hours.
for h = 1:24
battery_capacity(1) = initial_battery_capacity*number_batteries
if hourly_total_RES(h) > hourly_annual_demand(n), % battery charging
battery_capacity(h) = battery_capacity(h-1);
else
battery_capacity(h) = battery_capacity(h-1);
end
end
First off, the both sides of the if statement are the same as written. I assume that your actual code does some sort of work with the previous data. If not, that's a problem.
It also might make the code a little easier to think about if you switch the order of the day and hour loops. To me, looking through all the hours of one day at a time makes better sense than looking at the first hour of each day, then the second hour of each day...
As for the indexing, one definite error is that you index battery_capacity(h-1) on the first iteration of the loop. That is, when h is 1, you define battery_capacity(1) and then try to look at battery_capacity(0), which is probably what's throwing the error.
To fix this, you could check to see if h == 1, but I think a more elegant way would be to loop through h = 2:24 and set battery_capacity(1) before entering that loop. See if this code works:
for d = 1:number_of_days
battery_capacity(1) = initial_battery_capacity*number_batteries
for h = 2:24
if hourly_total_RES(h) > hourly_annual_demand(n), % battery charging
battery_capacity(h) = battery_capacity(h-1);
else
battery_capacity(h) = battery_capacity(h-1);
end
end
end
From what I understand, the last two dimensions store the hour and day respectively. So to set the value for first day at hour=1 (I assume this means midnight start of day):
battery_capacity(:,:,:,1,1) = 2; %# 2kWh
This will set the value 2 for all "panels" and all "turbines" and all "batteries".
I assume you have the matrix already pre-allocated somewhere in your code.
For what its worth, I think you have a typo where you first mention battery_capacity in the code (there is a missing h parameter)