How to generate matrix based on previous elements?

Hello all!
i will explain my problem , and i hope that you could help me because it's so critical.
i Have a matrix containing the arrival task (rows are tasks , columns are units of time slot), and each task take 3 units of time in processing.
A= [0 1 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 1 0 0 0 0 0 0 0 0 0];
i said that each task take 3 units of time so,i put this in other matrix B, the time waiting and in the processing indicated by "1".
  1. task 1 arrives in the second time slot(second column), will pass 3 sec in processing so will quit in time slot number 5.
  2. task 2 arrives in the third time slot , should wait 2 units for being executed and 3 units in processing, total 5 units of time.
  3. task 3 arrives in the third time slot also, should wait 5 units (because it should wait the first for 2 units, the second for 3 units of procesing) and 3 for its processing so the total =8 units of time.
  4. task for arrives in the 6th time slot,should wait task 2 for 2 units , task 3 for 3 units,and , the total = 8 units of time.
the matrix B is the result that i want: the "1" indicates the time explained above.
B= [0 1 1 1 1 0 0 0 0 0 0 0 0 0 0
0 0 1 1 1 1 1 1 0 0 0 0 0 0 0
0 0 1 1 1 1 1 1 1 1 1 0 0 0 0
0 0 0 0 0 1 1 1 1 1 1 1 1 1 0];
Please help me how to generate B?
HELP PLEASE!!

3 Comments

Don't whine...folks here are volunteers giving of their time.
@dpb i appreciate all their effort.
@Safia: Avoid the term "urgent", because it is couter-productive. See here.

Sign in to comment.

 Accepted Answer

A= [0 1 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 1 0 0 0 0 0 0 0 0 0];
maxj = find(A(1,:)==1);
for i = 1:size(A,1)
j = find(A(i,:)==1);
maxj = max(j + 3,maxj + 3);
B(i,1:j-1) = 0;
B(i,j:maxj) = 1;
end
B
B = 4×14
0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1

26 Comments

@Torsten thank you for you reply! the code you provided works only for the first row, but the others are the same no change.
Isn't the matrix B above exactly the matrix you expect to get ?
@Torsten yes it is , but B is the example, my real matrix is so large, i don't know why it doesn't work for other rows.
Maybe you have rows without a "1" or with several 1's in your "big" matrix.
@Torsten in each row , i have only "1". this is a part of my matrix A :
0 0 0 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
this is the result after using the code above:
0 0 0 1 1 1 1 0 0 0
0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1 1 1
and i verify with the sum of each row, i get :
4
4
47
6
4
4
4
18
i hope that you inderstand
i hope that you inderstand
No, I don't.
You didn't mention that you have zero rows (like the second and the fourth).
Should they be skipped in the process of building B ?
@Torsten attached is my matrix A , you can verify the code with it
What do you get if you apply the following code to your matrix A ?
S = sum(A,2);
any(S~=1)
And better supply the code that generated the matrix instead of the matrix itself.
@Torsten the matrix A was generated after a whole code so i can't supply the whole code, but B in this case depends only with elements in A.
Attached is the matrix A, the sum of each row,the matrix B after using your provided code, and the sum of each row of B
sumA has a 0 as last entry. So the last row of A is zero. Remove that row.
And if you have the matrix B, the code seems to work out fine, doesn't it ?
@Torsten no it doesn't work like i mentioned above..
For @dpb and @Torsten codes to work, your matrix A must satisfy the following conditions:
  1. Each row must contain exactly one 1.
  2. The column numbers in which the 1's appear are monotonically increasing, i.e. a case like A = [0 1 0; 1 0 0; 0 0 1] cannot be handled.
If these requirements are met, the code
maxj = find(A(1,:)==1);
for i = 1:size(A,1)
j = find(A(i,:)==1);
maxj = max(j + 3,maxj + 3);
B(i,1:j-1) = 0;
B(i,j:maxj) = 1;
end
should work. If not, you will have to show a matrix A for which it doesn't work as expected.
It works only with some rows,it seems that the problem in my matrix because I will focus on time (columns)of arriving task(rows),for example
A= [0 0 1 0 0 0 0
0 1. 0. 0. 0. 0. 0
1. 0. 0. 0. 0. 0. 0]
In this case, task 3 will be executed first because it is arriving first
Task 2 will be executed after 2 units
Task 1 is arriving last so it will wait the First for 1 second and task 2 for 4 units.(total 5) Matrix B will be like this:
B= [0 0 1 1 1 1 1 1
0 1. 1. 1. 1. 1. 1 0
1. 1. 1. 1. 0. 0. 0. 0]
I can't represent all elements
Then order your matrix A first:
A= [0 0 1 0 0 0 0
0 1. 0. 0. 0. 0. 0
0. 1. 0. 0. 0. 0. 0]
[I,~] = find(A==1)
A = A(I,:)
I hadn't seen this subthread ere now, but you keep adding stuff that wasn't in the original posting.
As @Torsten says, remove null rows; there can't be any point in keeping them it would seem...if, for some reason it is needed to know there are such, then
idxZ=find(~any(A,2));
will be the rows that were null in the original; numel(idxA) will be how many there were for bookkeeping
You then introduced the randomized first starting position that is a new wrinkle not in the original problem specification.
[A,idxA]=sortrows(A,[1:size(A,2)],'descend');
first; then use either mine or Torsten's code.
If needed, have the idxA array to produce the original order.
Or, you could process in the loop by stepping through with the idxA order instead of sequentially; just adds a bunch of additonal indirect addressing subscripting to the code; will leave that as "exercise for student" to actually do if want to go that way.
@dpb @Torsten thank you very much for your effort and extra time, now it works that i want. Many thanks for your help!
Safia
Safia on 27 Oct 2022
Edited: Safia on 27 Oct 2022
@Torsten Hi! i want to ask you if there is some rows are set to "zero", How can i change your provided code to get the same result. Thank you in advance.
Remove the zero rows:
ind = find(sum(A,2)==0) ;
A(ind,:) = [] ;
@Torsten Thank you! if i want to keep the same dimension of my matrix, it means i keep rows with zeros and apply the code for rows having "1". does it work with loop for?
Like this ?
A= [0 1 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 1 0 0 0 0 0 0 0 0 0];
I = 1;
while sum(A(I,:))==0
B(I,1) = 0;
I = I + 1;
end
maxj = find(A(I,:)==1);
for i = I:size(A,1)
if sum(A(i,:))==0
B(i,1) = 0;
continue
end
j = find(A(i,:)==1);
maxj = max(j + 3,maxj + 3);
B(i,1:j-1) = 0;
B(i,j:maxj) = 1;
end
B
B = 5×14
0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1
@Torsten the problem is when i apply an order for my matrix , only "1" are considered therefore "0" are eliminated and the dimension of matrix is changed.
Then count the number of zero rows + their positions in the matrix A, remove them, order A and reinsert the zero rows at the positions of your choice.
@Torsten thank you very much for your help!
Safia
Safia on 31 Oct 2022
Edited: Safia on 31 Oct 2022
@Torsten hi! i have a question if you don't mind ,how cant i put i condition to not exceed array bounds. I want to stop in the limit of my matrix. with your provided code, the number of columns increases over 100 iterations
I will be grateful if you could help me.Thnak you so much
A= [0 1 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 1 0 0];
I = 1;
while sum(A(I,:))==0
B(I,1) = 0;
I = I + 1;
end
maxj = find(A(I,:)==1);
for i = I:size(A,1)
if sum(A(i,:))==0
B(i,1) = 0;
continue
end
j = find(A(i,:)==1);
maxj = max(j + 3,maxj + 3);
if maxj > size(A,2)
break
end
B(i,1:j-1) = 0;
B(i,j:maxj) = 1;
end
B
B = 5×14
0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1

Sign in to comment.

More Answers (1)

dpb
dpb on 15 Oct 2022
Edited: dpb on 16 Oct 2022
dt=3; % use variables for data; don't bury magic numbers in code
[r,arr]=find(A); % get the arrival time each row
S=zeros(size(r)); E=S: % initialize start, end indices for each
S(1)=arr(1);
E(1)=arr(1)+dt;
for i=2:numel(r)
S(i)=max(E(i-1)+1,arr(i)); % next start is previous end+1 or arrival
E(i)=S(i)+dt;
end

13 Comments

@dpb thank you for your reply! in order to verify the result i use the sum of each row ,
4
1
1
1
1
1
1
1
1
1
1
1
1
1
1
it means that only the first row is considered.
What do you mean? The array B above is identical to what your posting says is the desired result...
B_posted=[0 1 1 1 1 0 0 0 0 0 0 0 0 0 0
0 0 1 1 1 1 1 1 0 0 0 0 0 0 0
0 0 1 1 1 1 1 1 1 1 1 0 0 0 0
0 0 0 0 0 1 1 1 1 1 1 1 1 1 0];
B_dpb =[ 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0
0 0 1 1 1 1 1 1 0 0 0 0 0 0 0
0 0 1 1 1 1 1 1 1 1 1 0 0 0 0
0 0 0 0 0 1 1 1 1 1 1 1 1 1 0 ];
all(B_posted==B_dpb)
ans = 1×15 logical array
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
shows it agrees for all four rows for all columns. What more can you ask?
The sum by column is
disp([sum(B_dpb,2) sum(B_posted,2)])
4 4 6 6 9 9 9 9
@dpb B is just an example for my real case. yes the code you posted is exact but works only for the first and the second rows. this is the result , but for other rows it still only "1".
0 1 1 1 1 0 0 0 0 0
0 0 0 1 1 1 1 1 0 0
0 0 0 0 0 0 0 0 0 0
You're going to have to have a different set of rules, then; and provide the other data in order for anybody to have even half a chance.
The above code follows the prescribed rules for any data set; if you change the rules, then all bets are off.
@dpb this part of code is exact
dt=3; % use variables for data; don't bury magic numbers in code
B=A; % initialize output array
[r,arr]=find(A); % get the arrival time each row
E=arr(1)+dt % initial end time
B(1,arr(1):E)=1;
the problem in loop
I don't believe it...gonna' have to show me, I'm a "doubting Thomas" without something concrete to look at.
Post your code and the data run against it in a runnable example.
Safia
Safia on 15 Oct 2022
Edited: Safia on 15 Oct 2022
@dpb my matrix is so "big" (380*3600), i can't show all elements to verify the code.
you can see my matrix attached
It doesn't need to be big to illustrate a condition you think my solution doesn't work for...and you haven't shown the code you used...my certainly will have operated over the full number of rows.
If there were some condition other than considered/not represented in the dataset have overlooked, then show us that condition.
It can happen in the first few rows and columns; just because you have a large real case doesn't matter; a 10x10 is surely big enough to represent any condition that might arise.
@dpb i don't have a condition expect, if the arrival the difference of time units between the arrival task.
for example , here "arr" display the time of arrival task :
arr =
54
56
60
81
160
182
191
214
240
263
there is a large difference between them, but as we see the case of the second arriving in time slot 56 should wait the first arriving in 54 for a unit ,because it doesn't finish yet (as i said each task take 3units of time). Did you understand the case?
See this example for A. I think it's not treated correctly.
A= [0 1 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 0];
dt=3; % use variables for data; don't bury magic numbers in code
B=A; % initialize output array
[r,arr]=find(A); % get the arrival time each row
E=arr(1)+dt; % initial end time
B(1,arr(1):E)=1;
for i=2:numel(r)
E=E+dt
B(i,arr(i):E)=1;
end
E = 8
E = 11
E = 14
B
B = 4×15
0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
I see I ended up pasting the wrong code in; it was a first pass I pulled from the commandhistory instead of the later -- it did produce the correct answer for the sample but didn't correctly consider the disparate distances, but then I just looked at the result instead of the code not realizing what had done...
I updated the Answer to reflect; I think this does what you want for the S (start) and E (end) values; it presumes the next START cycle can't be until one AFTER the previous end; if your counting is that the next START can be the same increment as the previous end, remove the "+1" adjustment...then if you're still using the large array of ones and not just the much-more-storage-efficient indices, then fill it between S:E for each row.
How can I get the result no after update code ?
What you mean? Have all start/end values; just stuff those into an array if still using.
dt=3; % use variables for data; don't bury magic numbers in code
[r,arr]=find(A); % get the arrival time each row
S=zeros(size(r)); E=S: % initialize start, end indices for each
S(1)=arr(1);
E(1)=arr(1)+dt;
B(1:S(1):E(1))=1;
for i=2:numel(r)
S(i)=max(E(i-1)+1,arr(i)); % next start is previous end+1 or arrival
E(i)=S(i)+dt;
B(i:S(1):E(1))=1;
end

Sign in to comment.

Categories

Find more on Get Started with MATLAB in Help Center and File Exchange

Tags

Asked:

on 15 Oct 2022

Commented:

on 1 Nov 2022

Community Treasure Hunt

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

Start Hunting!