Choose a cell array that satisfy better some criteria

Given two arrays
A = [45 41 19 32 32 15 24 1 41 15 15 15 15];
B = [200 200 200 200 200 200 200 200 200 200 200 200 200];
I want to make the difference, substracting A from B and obtaining
C = [155 159 181 168 168 185 176 199 159 185 185 185 185];
Now I want to ordinate the cloumns of C and obtain a vector with column number from higher value to loerr one. Note for example that the highest value is 199, so column 8. then we have 185 so 6, 10, 11, 12,13 . At the end we will have an array we all the columns number from higher value to lower one
D = [8 6 10 11 12 13 3 7 4 5 2 9 1];
Now I want to create a vector from D that I will use to make comparison with other arrays. In particular I give weigth from 13 to 1, at all the values in D, creating E
E = [13 12 11 10 9 8 7 6 5 4 3 2 1];
Where 13 refers to element 8, 12 to element 6, 11 to element 10 and so on.
From array E we derive the number 13121110987654321, that we will use for comparison we other vector.
Now we have a cell array
VM = {[46 41 24 33 32 15 41 19 0 13 15 14 15]; [0 2 41 10 9 32 9 32 41 31 31 31 31];[13 10 19 3 2 41 0 20 41 41 41 41 41]}
For each cell of VM I want to do same, taking for example the first cell
VM{1,1}= [46 41 24 33 32 15 41 19 0 13 15 14 15];
I want to do thefollowing and ordinate the column from the higher to lower obttaining
F=[1 2 7 4 5 3 8 6 11 13 12 10 9]
As we can see the highest value is 46 so I put one in front. then 41 so I put 2.
Then I have to make comparison between F and E. for each element of F I wan to report how many values has that element in front of it in E. So for example, taking the first element of F: 1.
1 in E has 0 element in front of it. so I create a new vector G with 0 in front. element 2 has 2 element in front of it so I put 2. 7 has 6 element. 4 has 3 and so on
G = [0 1 6 3 4 2 7 5 10 12 11 9 9]
the array G give as a result the number 163427510121199, later we will compare this number with the one obtained in E.
Taking now the second cell
VM{1,2} = [0 2 41 10 9 32 9 32 41 31 31 31 31];
I obtain again
F = [3 9 6 8 10 11 12 13 4 5 7 2 1];
again
G = [2 8 5 7 9 10 11 12 3 4 6 1 0];
In this case we obtain a number 2857910111234610
The number obtained in each cell of VM has to be reported in a vector and
BB= [163427510121199, 2857910111234610, ...] and made a comparison with the one obtained from E: 13121110987654321.
As expected the one in E is the highest one. Now we want to give a weight to the one obtained in BB. Remember that the higher the better. the hogher value in BB will have a value of 200 (fixed) then going down to the ohter I want a value every time reduced by 3. so 200, 197, 194 and so on.
In thi case from BB we will have
HH = [197, 200 , ..].
So the main Idea is evertime to select the cell array in VM that summed to inital vector A, allow us to enhance the A quantity following the values in B, without producing more in one column with respect to the others.
SIMPLER SOLUTION ARE WELL ACCEPTED
May someone help me with the code?

14 Comments

1) Do you have any of the code written so far? If so, please post it here.
2) Why are you weighing D from highest to lowest with 13 - 1, but then F gets weighed from highest to lowest with 1 - 13? Also, if VM{1,1}(9) = 0, why is F(9) not 13?
3) I'm not entirely sure how you are creating G. It looks like you are just doing F(:)-1 (except for the last element; is that a typo?)
4) During VM{1,2} you create F and E. Is that supposed to be F and G? It look like the E being created here is the same process as the previous G.
5) What is the point of all this? There may be a simpler solution, but I don't understand the greater purpose of what you're trying to accomplish.
1) I haven't write a code so far
4) Yes sorry was G
5) The main purpose of the code is
given an array A with quantities
A = [45 41 19 32 32 15 24 1 41 15 15 15 15];
it means that we have 45 parts of element 1, 41 parts of 2, 19 parts of 3 and so on.
When I talk about elements i means the column, element = column
The final objective is
B = [200 200 200 200 200 200 200 200 200 200 200 200 200];
so given the cell VM. I want to select the vector in VM that, summed to A, allow to closely come to the final value of B. That is, if element 8 in A is just 1, the next vector should contain preferably more parts of 8, so high vaues in column number 8.
2) for what concerne this question i didnt get what you mean. Both D and F contains the elements. that are thriteen=number of columns. And in both of the arrays they are ordered on the basis of C and VM respectively.
So if in C, element=column=1 has the highest value, then in D I will found 1 in the first position and so on.
3) G is creating just looking at Fand and E. we iterate on each element of F. Now, taking the first cell. The first element if F is 1. Then we look at element 1 in E, and we ask: how many elements/columns has 1 in front of him? the answer is 0. cause 1 in E is the last number.
then in F we found 2. how many elements/columns has 2 in front of him? the answer is 1. cause 2 in E has one column in frton of it
I hope now its clear.
FYI, matlab convention calls an 'element' as a single piece of data within an array, which has an address defined by a row, column, sheet, etc. For example, VM{1}(1,1) is an element of VM which is found in the first row, '(1,' and first colum, '1),' of the first cell '{1}' of the VM cell array. I will be using that naming convention from now on.
2) My understanding is that D and F are the indices corresponding to the appropriate descending order position of the elements of C and VM. D and F do not contain the actual values that these indices correspond to, merely their position within the heirarchy. As such, I understand how these two can be related, but I am not sure how E relates to the issue. As far as I'm concerned, E is literally just a descending order array from 13 -> 1 which will be constant, independant of the order of D, F, or any other array.
3) From what you have described, G will always be F - 1. This is because a) E is always a descending order of integers from 13 -> 1, and b) you are not asking about the value of the element of E, just the position, which will not change. Are you sure you don't want to compare the values of F and D, and determine the difference in positions there?
5) This is going to be my main point to come back to. I think I understand a little bit better what you're trying to do. You want to get C, because it is the difference in number of elements for each column. You want to compare A and VM to determine which ones are closest. I am still confused as to what the purpose of this comparison is though. Are you just trying to find which row of VM is closest in size to A? I would like to help as much as I can, and while I can just write some code that does the steps you have asked, if I can get a picture from a step further back we might be able to get a much more concise method written out for you.
luca
luca on 11 Oct 2019
Edited: luca on 11 Oct 2019
3) you are right , G will always be F - 1.. Lets read below to understand why I want to compare G and E.
2 and 5)
In order to understand better I explain you my cycle. I have a for loop and at every iteration I generate a new A. Inside the loop I can choose different sequences. All the possible sequence are included in VM. Now I want to select the sequecne inside VM, that best fit the final goal B as I explain you before. Outside the for loop I have a variable YY that collect and sum the A that are generated at each iteration. after x iteration I want to reach the final objective indicated in B. to do so I need to chose the best sequence every time
And yes you are right. E is just a descending order from 13 to 1.
The problem is that my method it works just when the number of columns is less then 10.
if for example they are 9:
E = [9 8 7 6 5 4 3 2 1] . the sequecne generate a number 9 8 7 6 5 4 3 2 1. Due to the fact that the disposition in E is the best for my goal, all the other number sequence generated in G are lower.
for example a sequence G = [4 5 6 7 8 9 1 2 3] give a number 456789123 that is lower.
a sewuence G = [ 8 9 7 1 2 3 4 5 6] give a number 897123456 that is better than 456789123, so I will assign 200 to 897123456 and 197 to 456789123.
But if I exceed 10 then this method is no mroe valid. cause 10 is read from matlab as 1 and 0.
I need to find anther solution. May you help me?
Hmm, ok, I'm getting a better picture of what you're trying to do.
What is the purpose of looking at, and comparing the different locations of the numbers? Why wouldn't you just look at the values (because you're trying to ultimately compare to B, which is value based)?
The purpose is to find that numbers like “ 456789123” described above, and comparing all of them with the one derived in E .
In this way we can understand which sequence is better to grow uniformly and reach the objective B
What do you mean by look at the values ?
In A and B you have values, which you are comparing to find the differences. Every other array, except VM, contains position information, rather than the direct data numbers.
As for comparing position information with more than 9 numbers, I recommend doing a direct element comparison, rather than a concatonated comparison. Just use some logic setup.
check = find(A==VM{1});
The value of check will then be the elements of A, or VM{1}, that match each other.
But for example, if in A I have a low value in column 5, then I want to select a VM array that contain an high value in column 5! In order to balance the production and reach before the final goal . I don’t know if your idea works
Mmm, ok, I think I see what you mean. Let me think about it over the weekend. I will get back to you if nobody else responds by then. Sorry for not having a more prompt solution.
No problem! Thanks for the help. If you need more info let me know ! I’m here
Do you have some news?

Sign in to comment.

 Accepted Answer

Bob Thompson
Bob Thompson on 14 Oct 2019
Edited: Bob Thompson on 14 Oct 2019
Ok, here is what I have come up with. It will probably still need some tweaking, but you should be most interested in the calculation of BB. I don't know how else to get around the problem you had with numbers greater than 9, so I just compared the individual element locations, and found the smallest difference in positions. It's just a for loop, but written more nicely with arrayfun.
A = zeros(1,13);
while A < B % Loop through selection until A exceeds B. Can be changed to for loop of you want
C = B - A; % Get difference between A and B
[~,C] = sort(C,2,'descend'); % Determine descending order index of differences. Set to have biggest difference as #1 (Formerly D)
C(2,:) = [1:13]; % Add a relative position array (technically doesn't need to happen each loop (Formerly E)
for i = 1:size(VM,1) % Loop through different VM sets. Can be done with cells if you want, but I like matrices better
[~,tmp(i,:,1)] = sort(VM(i,:),2,'descend'); % Determine descending order index. Set to have biggest number as #1 (Formerly F)
tmp(i,:,2) = [1:13]; % Add a relative position array (Not previously created)
BB(i) = sum(abs(arrayfun(@(x) C(2,C(1,:)==x)-tmp(i,tmp(i,:,1)==x,2),C(1,:)))); % Compare relative positions of each element and find difference. Sum the values (Formerly G and some other things)
end % VM loop
A = A + VM(BB == min(BB),:); % Add values with smallest difference in positions to A. Loop begins again after this
end % A size check loop
The while loop ends when any element of A reaches or exceeds the relative element of B (i.e. when any element of A >= 200)
Also, note that I have VM as a 2D array, rather than a cell array. You can use the cell array you already have, just make sure you adjust the for loop indexing properly.

5 Comments

Do you think that compare the position its enough to arrive to the best solution?
I am not entirely sure. This level of logical analysis is not my strong suit (the actual math portion, though I suppose the matlab as well). I think that the summing of differences helps though.
luca
luca on 14 Oct 2019
Edited: luca on 14 Oct 2019
I'm studiyng your code. And yes it can works. But running it I ve seen how most of the time it doesn't work optimally.
To make it work in the best way we should give a weight to some value when the difference between B and A is high for some elements with respect to the others. in this case we should prefer the sequence that enhance that value. Do you think its possible to implement?
That's fair. It's definitely possible to implement something like that, but I don't have time to think through the logic thoroughly enough to provide you with a good solution. If you can write out the logic you want I can help you turn it into code.
Thnaks Bob . I will try to do it

Sign in to comment.

More Answers (0)

Products

Release

R2019b

Asked:

on 11 Oct 2019

Commented:

on 14 Oct 2019

Community Treasure Hunt

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

Start Hunting!