how to determine the relative position of a number in a matrix

3 ビュー (過去 30 日間)
user3490
user3490 2020 年 1 月 3 日
コメント済み: user3490 2020 年 1 月 4 日
I have a matrix consisting of 1, 0, -1 where
type_vec = [1 0 -1];
and create a permutation matrix using the permn function available online
mat_n_dim = 4;
perm_mat = permn(type_vec , mat_n_dim);
The goal is to generate a matrix where:
  • In a single row, there is never a 1 to the right of -1 e.g.
perm_mat = [1 0 0 0 % valid
1 0 0 1 % valid
1 0 0 -1 % valid
1 0 -1 0 % valid
-1 0 0 1 % not valid
1 -1 -1 1 % not valid
];
By finding the valid rows and eliminating the unvalid rows.
I realize it is possible to do that using for loops and if statements but I was wondering if there is a way to do it using the matlab functions

採用された回答

Stephen23
Stephen23 2020 年 1 月 3 日
編集済み: Stephen23 2020 年 1 月 3 日
>> M = [1 0 0 0 % valid
1 0 0 1 % valid
1 0 0 -1 % valid
1 0 -1 0 % valid
-1 0 0 1 % not valid
1 -1 -1 1 % not valid
1 1 -1 1]; % not valid (from your comment)
>> invalid = any(cumsum(M<0,2) & M>0, 2)
invalid =
0
0
0
0
1
1
1
  3 件のコメント
Stephen23
Stephen23 2020 年 1 月 3 日
編集済み: Stephen23 2020 年 1 月 3 日
@reebal nimri: see my edited answer, it seems to fulfill your specification:
>> V = [+1,0,-1];
>> M = permn(V,4);
>> X = any(cumsum(M<0,2) & M>0,2);
>> Z = M(~X,:)
Z =
1 1 1 1
1 1 1 0
1 1 1 -1
1 1 0 1
1 1 0 0
1 1 0 -1
1 1 -1 0
1 1 -1 -1
1 0 1 1
1 0 1 0
1 0 1 -1
1 0 0 1
1 0 0 0
1 0 0 -1
1 0 -1 0
1 0 -1 -1
1 -1 0 0
1 -1 0 -1
1 -1 -1 0
1 -1 -1 -1
0 1 1 1
0 1 1 0
0 1 1 -1
0 1 0 1
0 1 0 0
0 1 0 -1
0 1 -1 0
0 1 -1 -1
0 0 1 1
0 0 1 0
0 0 1 -1
0 0 0 1
0 0 0 0
0 0 0 -1
0 0 -1 0
0 0 -1 -1
0 -1 0 0
0 -1 0 -1
0 -1 -1 0
0 -1 -1 -1
-1 0 0 0
-1 0 0 -1
-1 0 -1 0
-1 0 -1 -1
-1 -1 0 0
-1 -1 0 -1
-1 -1 -1 0
-1 -1 -1 -1
user3490
user3490 2020 年 1 月 4 日
Can you elaborate on the method?
Much appreciated, thanks!

サインインしてコメントする。

その他の回答 (1 件)

Walter Roberson
Walter Roberson 2020 年 1 月 3 日
first_1_pos = min( (perm_mat == 1) .* (-mat_n_dim:-1), 2 );
first_n1_pos = min( (perm_mat == -1) .* (-mat_n_dim:-1), 2 );
valid_row = first_n1_pos >= first_1_pos;
perm_mat = perm_mat(valid_row, :);
This declares a row to be valid if it has no -1, even if it has no 1 as well.
1 -1 -1 1 % not valid
No, that row is valid according to the rules you have defined. Every -1 is to the right of some +1.
Defining that there is never a 1 to the right of -1 would be a different rule.
You should document your rules for yourself.
  • what if there are no 0, is that valid?
  • what if there are no -1, is that valid?
  • what if there are no +1, is that valid?
  • What if every -1 is to the right of some +1, is that valid?
  • What if every -1 is to the right of every +1, is that valid? Even if there are no +1 ?
  3 件のコメント
Walter Roberson
Walter Roberson 2020 年 1 月 3 日
first_1_pos = min( (perm_mat == 1) .* (-mat_n_dim:-1), [], 2 );
first_n1_pos = min( (perm_mat == -1) .* (-mat_n_dim:-1), [], 2 );
valid_row = first_n1_pos >= first_1_pos;
perm_mat = perm_mat(valid_row, :);
This has not been adjusted for your revised rule that there is never a 1 to the right of a -1; this is still for the rule that any -1 must be to the right of some 1. I would need to think more about the best way to adapt for the revised rule.
With regards to the method used:
(perm_mat == 1) .* (-mat_n_dim:-1)
compares each value to 1, giving an array of 0 (not equal to 1) and 1 (is equal to 1). This is then multiplied by the vector -4 -3 -2 -1 which is automatically replicated to the correct number of rows (requires R2016b or later). The positions that are not 1 get zeroed out, leaving for example,
-4 0 0 0
-4 0 0 -1
-4 0 0 0
-4 0 0 0
0 0 0 -1
-4 0 0 -1
The more negative the number, the further left it is. Now, min() along the rows; in the above case you would get [-4; -4; -4; -4; -1; -4] . The effect of the min() on that arrangement of negative values and 0's is to identify per-row what the left-most position is that is equal to +1, counting from the right hand side (-1 is the last column, -2 for the second last, -3 for the third last, -4 for the fourth last, etc.) If no positions were equal to 1, then all of the entries after the multiplication would be 0, and min() of those 0 would be 0. Notice that if we had done a straight numbering from the left, [1 2 3 4] that we would have had the issue that min() between a positive number and 0 is 0. [The revised version of the code for your new rule will involve positive counts and max() in order to find the right-most +1]
We then do the same thing with comparing to -1 . Again, we get out a value that is most negative the further left we are, and 0 if there are no occurrences.
We can now compare the relative values of the position of the first -1 and the position of the first +1: a position to the right is less negative and so > comparison works in the case that both are present.
You do have to be careful about the case where only one of them is present. If there is no -1 then the value for that first_n1_pos will be 0, and that is greater than any negative value expressing the position of the first +1, and that works out fine because the (original) rule is that -1 if present must be to the right of some +1 . If the -1 was present but no +1 then the negative first_n1_pos would not be greater than the 0 of the first_1_pos, and you would fail, but that is fine because that case would violate the (original) rule that any -1 present must be to the right of some +1 .
This all said... I like how compact Stephen's code is, and I suspect his code could be fixed to match your needs.
user3490
user3490 2020 年 1 月 4 日
Thank you for your help, much appreciated!

サインインしてコメントする。

カテゴリ

Help Center および File ExchangeStructures についてさらに検索

Community Treasure Hunt

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

Start Hunting!

Translated by