If I know that K = kron ( A , B ),where kron is the Kronecker product of matrices as defined in MATLAB, how can I find A and B from a given matrix K?
for example suppose that
K = [1 0 0 0 ;0 1 0 0 ; 0 1 0 0 ;0 1 0 0 ;1 0 0 0 ;0 1 0 0 ;0 1 0 0 ;0 1 0 0 ;1 0 0 0 ;0 1 0 0 ;0 1 0 0 ;0 1 0 0 ;0 0 1 0 ;0 0 0 1 ;0 0 0 1 ;0 0 0 1 ]
is there any way to find A and B, such that K = kron ( A , B )?
In this case, A and B are as follows:
A = [ 1 0 ; 1 0 ; 1 0 ; 0 1 ]
B = [ 1 0 ; 0 1 ; 0 1 ; 0 1 ]
Short Discussion and Solution Code
You can't find both A and B, given a K, because there could be many possible A's and B's to produce a certain kron matrix, K. Thus, alongwith K, you need either A or B to get the remaining input B or A respectively.
Case #1 Given A and K (kron matrix), you can find B with -
B = K(1:size(K,1)/size(A,1),1:size(K,2)/size(A,2))./A(1)
Case #2 Given B and K (kron matrix), you can find A with -
A = K(1:size(B,1):end,1:size(B,2):end)./B(1)
Thus, if not the entire other input, you would at least need to know the size of it and one of the elements of it, preferably the first element.
Function Code
You can very easily convert that to a function code for an easy plug-n-play usage -
%// INVERSE_KRON Inverse of Kronecker tensor product to find one of the inputs.
% // INVERSE_KRON(K,ARRAY,INPUT_ID) finds one of the inputs used for calculating the
% // Kronecker tensor product given the other input and the ID of that other input.
% // Thus, if K was obtained with K = KRON(A,B), one must use -
% // A = INVERSE_KRON(K,B,2) to find A, and
% // B = INVERSE_KRON(K,A,1) to find B.
function out = inverse_kron(K,array,input_id)
switch input_id
case 1
out = K(1:size(K,1)/size(array,1),1:size(K,2)/size(array,2))./array(1);
case 2
out = K(1:size(array,1):end,1:size(array,2):end)./array(1);
otherwise
error('The Input ID must be either 1 or 2')
end
return;
Typical use case would look like this -
K = kron(A,B); %// Get kron product
A = inverse_kron(K,B,2) %// Recover A
B = inverse_kron(K,A,1) %// Recover B
Note: For a vector case, one other related question and answer could be found here.
Related
I want to obtain all the possible permutations of one vector elements by another vector elements. For example one vector is A=[0 0 0 0] and another is B=[1 1]. I want to replace the elements of A by B to obtain all the permutations in a matrix like this [1 1 0 0; 1 0 1 0; 1 0 0 1; 0 1 1 0; 0 1 0 1; 0 0 1 1]. The length of real A is big and I should be able to choose the length of B_max and to obtain all the permutations of A with B=[1], [1 1], [1 1 1],..., B_max.
Thanks a lot
Actually, since A and B are always defined, respectively, as a vector of zeros and a vector of ones, this computation is much easier than you may think. The only constraints you should respect concerns B, which shoud not be empty and it's elements cannot be greater than or equal to the number of elements in A... because after that threshold A will become a vector of ones and calculating its permutations will be just a waste of CPU cycles.
Here is the core function of the script, which undertakes the creation of the unique permutations of 0 and 1 given the target vector X:
function p = uperms(X)
n = numel(X);
k = sum(X);
c = nchoosek(1:n,k);
m = size(c,1);
p = zeros(m,n);
p(repmat((1-m:0)',1,k) + m*c) = 1;
end
And here is the full code:
clear();
clc();
% Define the main parameter: the number of elements in A...
A_len = 4;
% Compute the elements of B accordingly...
B_len = A_len - 1;
B_seq = 1:B_len;
% Compute the possible mixtures of A and B...
X = tril(ones(A_len));
X = X(B_seq,:);
% Compute the unique permutations...
p = [];
for i = B_seq
p = [p; uperms(X(i,:).')];
end
Output for A_len = 4:
p =
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 1 0 0
1 0 1 0
1 0 0 1
0 1 1 0
0 1 0 1
0 0 1 1
1 1 1 0
1 1 0 1
1 0 1 1
0 1 1 1
I have a 3D matrix A (size m*n*k) where m=latitude, n*longitude and k=time.
I want only specific values from first and second dimension, specified by a logical matrix B (size m*n), and I want only the timesteps specified by vector C (size k).
In the end this should become a 2D matrix D, since the first two dimesions will colapse to one.
What is the most easy approach to do this?
And also is it possible to combine logical with linear indizes here? For example B is logical and C is linear?
Sample code with rand:
A=rand(10,10,10);
B=randi([0 1], 10,10);
C=randi([0 1], 10,1);
D=A(B,C) %This would be my approach which doesnt work. The size of D should be sum(B)*sum(c)
Another example without rand:
A=reshape([1:27],3,3,3);
B=logical([1,0,0;1,0,0;0,0,0]);
C=(1,3); %get data from timestep 1 and 5
D=A(B,C);%What I want to do, but doesnÄt work that way
D=[1,19;2,20];%Result should look like this! First dimension is now all data from dimesion 1 and 2. New dimesion 2 is now the time.
A = rand(4,4,4);
B = randi([0 1], 4,4)
B =
1 1 0 1
1 0 1 1
0 0 1 0
1 0 1 1
>> C = randi([0 1],1,1,4);
>> C(:)
ans =
0
1
1
0
Then use bsxfun or implicit expansion expansion whith .* if newer Matlab version to generate a matrix of logical for you given coordinates.
>> idx = logical(bsxfun(#times,B,C))
idx(:,:,1) =
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
idx(:,:,2) =
1 1 0 1
1 0 1 1
0 0 1 0
1 0 1 1
idx(:,:,3) =
1 1 0 1
1 0 1 1
0 0 1 0
1 0 1 1
idx(:,:,4) =
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
Then your output is D = A(idx). However, note that this D is now an Nx1 array. Where N is number of true elements is B times number of true elements in C. 10x True in B and 2x True in C:
>> size(D)
ans =
20 1
An easy way to do it is to first reshape A into an m*n-by-k matrix, then do your indexing:
result = reshape(A, [], size(A, 3));
result = result(B, C);
In this case C can be either a logical vector or vector of indices.
I have m input variables I_1, ..., I_m to a decision. Each variable may have n possible values. The decision outcome D is binary.
A decision rule R is a mapping from set D x I_1 x ... x I_m onto the set {0, 1} such that for any (i_1, ..., i_m) in I_1 x ... x I_m it holds that 1 = sum_(d in D) R(d, i_1, ..., i_m). That is: for any combination of input values only one decision is possible.
For example without any input variable you have two decision rules:
D R1 R2
a 0 1
b 1 0
That is the rule R1 selects decision b while R2 selects a.
With one binary input variable I you have four possible decision rules:
I D R1 R2 R3 R4
0 a 0 0 1 1
0 b 1 1 0 0
1 a 0 1 0 1
1 b 1 0 1 0
That is the decision rule R2 selects b if input is 0 and it selects a if input is 1.
With two binary input variables I and K you have 16 possible decision rules
I K D R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16
0 0 a 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1
0 0 b 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0
1 0 a 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1
1 0 b 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0
0 1 a 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1
0 1 b 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0
1 1 a 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
1 1 b 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
My question how can I enumerate all possible decision rules for an arbitrary set of input variables?
Disclaimer: This is part of a homework. However the homework is restricted to the case with one binary input variable such that one can simply enumerate all four cases. I passed this part of my homework - actually an enumeration is not necessary at all - but I am interested in a general solution in matlab.
How can I enumerate all possible decision rules for an
arbitrary set of input variables?
First by analyzing and understanding the repetitive patterns that are visible when we write down the binary permutations of the decision rules (R), based on the number (n) of input variables (V). And then building a set functions that generate these permutations automatically and display a table with the results like you would do it by hand.
In terms of code, there are many different valid approaches to solve this problem, but from my point of view, I think that working with a matrix of logicals is a good way to do it. I will call this matrix (M). This matrix has three parts (like the tables in your description):
Left: n columns for the input variables (V)
Center: 1 column for the decision (D)
Right: 2^(2^n) columns for the decision rules (R)
And since your problem has two decisions (A and B), we can treate them as logical values too:
A = 0
B = 1
Note: I chose this values for A and B, and not the opposite ones, because it allows us to generate the binary permutations (which I will call "states") of the input variables (V) and the decision (D) using natural binary count.
For n = 0, M looks like:
0 0 1
1 1 0
For n = 1, M looks like:
0 0 0 0 1 1
0 1 1 1 0 0
1 0 0 1 0 1
1 1 1 0 1 0
For n = 2, M looks like:
0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1
0 0 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1
0 1 1 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0
1 0 0 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1
1 0 1 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0
1 1 0 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
1 1 1 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
And the size of M grows up pretty quickly as you mentioned:
Rows ("states") grow at a rate of 2^(n + 1)
Columns grow at a rate of (n + 1) + 2^(2^n): n columns for input variables + 1 column for decision (D) + 2^(2^n) columns for decision rules (R).
From the previous matrices we can hardly tell apart any repetitive patterns, but if we use colors we can clearly see some patterns in the decision rules (R) region:
For n = 0:
For n = 1:
For n = 2:
We can see that there are row-wise copies of the same "unit pattern" (boxed digits). Each "unit pattern" is 2 rows wide and 2^(2^n)/k columns wide (where k is the number of repetitions of a pattern for every two rows). The first pattern in M is always a single copy (k = 1), and k duplicates every 2 rows.
We will use all this information to create a set of functions that will allow us to enumerate all the possible decision rules through the use of a table that I will call (T).
I wrote a function called CalcParams which calculates all the necessary parameters of the problem (such as number of rows and columns of M, etc.) based on n:
function[a, b, c, d, e] = CalcParams(n)
% Calculate necessary parameters.
% Inputs:
% n - number of input variables.
% Number of states (rows).
a = 2^(n + 1);
% Number of decision rules (R) (decision rules columns).
b = 2^(2^n);
% Column index of first decision rule (R1).
c = n + 2;
% Number of columns of input variables (V) and decision (D).
d = n + 1;
% Total number of columns.
e = d + b;
end
Then I wrote a function called ValidDecRules which given n and M, checks if the input decision rules meet the requirement:
For any combination of input variables only one decision is possible.
If the decision rules meet the requirement the function returns 1 and displays the message VALID decision rules, otherwise the function returns 0 and displays the message INVALID decision rules.
function[val] = ValidDecRules(n, M)
% This function checks if the input decision rules meet the requirement:
% For any combination of input variables only one decision is possible.
% Inputs:
% n - number of input variables.
% M - binary matrix.
% Calculate necessary parameters.
[~, ~, c, ~, e] = CalcParams(n);
% Invalid decision rules by default.
val = 0;
% Extract odd rows from decision rules (R).
M_odd = M(1:2:end, c:e);
% Extract even rows from decision rules (R).
M_even = M(2:2:end, c:e);
% Check that all elements of the odd rows are different than the elements
% of the even rows.
if(all(all(M_odd ~= M_even, 1), 2))
% Valid decision rules.
val = 1;
disp('VALID decision rules');
else
% Invalid decision rules.
disp('INVALID decision rules');
end
end
Then I wrote a function called GenM which generates the binary matrix M based on n, and if you use the optional argument 'plot' it will plot the decision rules of M using imagesc.
function[M] = GenM(n, varargin)
% This function generates the binary matrix M.
% Inputs:
% n - number of input variables.
% Options:
% 'plot' - plot decision rules of M.
% Calculate necessary parameters.
[a, b, c, d, e] = CalcParams(n);
% Anonymous functions.
f1 = #(v, k) uint8(repmat(v, 1, k));
f2 = #(v, k) f1([v; ~v], k);
f3 = #(b, k) f2([false(1, b/(2*k)), ~false(1, b/(2*k))], k);
% Binary permutations of input variables (V) and decision (D).
Dec = 0:a-1; % Array: decimal representation of every state.
Bin = dec2bin(Dec); % Array: binary representation of every state.
% Preallocate matrix M.
M(length(Bin), d) = 0;
% Loop: input variables (V) and decision (D).
% Writes binary states in matrix M.
for i = 1:d
M(:, i) = uint8(str2num(Bin(:, i)));
end
% Loop: decision rules.
% Writes binary permutations of decision rules (R) in matrix (M).
% Start with k = 1.
k = 1;
for i = 1:2:a
M(i:(i + 1), c:e) = f3(b, k);
k = k*2;
end
% Continue only if decision rules (R) are valid.
if(ValidDecRules(n, M))
% Plot decision rules if 'plot' option is used.
if(~isempty(varargin))
if(any(strcmp(varargin, 'plot')))
% Visualize decision rules as image.
imagesc(M(:, c:e));
title('Decision Rules (R)');
colormap summer;
axis off;
end
end
else
% If decision rules are invalid, return empty output.
M = [];
end
end
Finally I wrote a function called EnumDecRules which takes n and generates a table T very similar to the ones on the description of your question. The function also returns the binary matrix M that was used to generate T. And if you use the 'plot' optional argument, it will plot the decision rules of M (like the GenM function).
The EnumDecRules function is the one that really answers your question because it has the behaviour that you are asking for.
function[T, M] = EnumDecRules(n, varargin)
% This function generates the table (T) with the results and also returns
% the binary matrix M that was used to generate T.
% Inputs:
% n - number of input variables.
% Options:
% 'plot' - plot decision rules of M.
% Calculate necessary parameters.
[a, ~, ~, d, e] = CalcParams(n);
% Generate the binary matrix M.
M = GenM(n, varargin{:});
if(~isempty(M))
% Loop: variable names to diplay in table header.
% Initialize indexes for numbering.
Vi = 1; % Input variable numbering index.
Ri = 1; % Decision rules numbering index.
for i = 1:e
if i <= n
% Input variables.
% Write V[Vi].
Names{i} = ['V', sprintf('%d', Vi)];
% Increase index.
Vi = Vi + 1;
elseif i == d
% Decision.
% Write D.
Names{i} = 'D';
elseif i > d
% Decision rules.
% Write R[Ri].
Names{i} = ['R', sprintf('%d', Ri)];
% Increase index.
Ri = Ri + 1;
end
end
% Generate table with results.
T = array2table(M, ...
'VariableNames', Names);
% Modify decision column (D) of table.
% Replace 0 with 'A'.
% Replace 1 with 'B'.
T.D = repmat({'A'; 'B'}, a/2, 1);
else
% If M is empty, return empty output.
T = [];
end
end
Usage example:
Make sure you save all the functions correctly in the same directory.
Example 1:
Call the EnumDecRules function to enumerate all possible decisions rules for n = 1:
[T, M] = EnumDecRules(1)
These are the outputs:
VALID decision rules
T =
V1 D R1 R2 R3 R4
__ ___ __ __ __ __
0 'A' 0 0 1 1
0 'B' 1 1 0 0
1 'A' 0 1 0 1
1 'B' 1 0 1 0
M =
0 0 0 0 1 1
0 1 1 1 0 0
1 0 0 1 0 1
1 1 1 0 1 0
Example 2:
Call the EnumDecRules function to enumerate all possible decisions rules for n = 2 and also plot the decision rules:
[T, M] = EnumDecRules(2, 'plot')
These are the outputs:
VALID decision rules
T =
V1 V2 D R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16
__ __ ___ __ __ __ __ __ __ __ __ __ ___ ___ ___ ___ ___ ___ ___
0 0 'A' 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1
0 0 'B' 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0
0 1 'A' 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1
0 1 'B' 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0
1 0 'A' 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1
1 0 'B' 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0
1 1 'A' 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
1 1 'B' 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
M =
Columns 1 through 9
0 0 0 0 0 0 0 0 0
0 0 1 1 1 1 1 1 1
0 1 0 0 0 0 0 1 1
0 1 1 1 1 1 1 0 0
1 0 0 0 0 1 1 0 0
1 0 1 1 1 0 0 1 1
1 1 0 0 1 0 1 0 1
1 1 1 1 0 1 0 1 0
Columns 10 through 18
0 0 1 1 1 1 1 1 1
1 1 0 0 0 0 0 0 0
1 1 0 0 0 0 1 1 1
0 0 1 1 1 1 0 0 0
1 1 0 0 1 1 0 0 1
0 0 1 1 0 0 1 1 0
0 1 0 1 0 1 0 1 0
1 0 1 0 1 0 1 0 1
Column 19
1
0
1
0
1
0
1
0
And the plot:
Since this type of algorithm grows so fast, using EnumDecRules or GenM for n >= 5 can result in an out of memory error.
I really hope this will be helpful. If you have any questions about specific instructions of the code please leave a comment and I will be happy to answer them.
I have a matrix A which is
A=[1 0 0 1 0;
0 1 1 0 0;
0 0 1 1 0;
1 1 1 0 0]
And a given vector v=[ 0 0 1 1 0] which has two elements one. I have to change the position of element one such that the new vector v is orthogonal to all the rows in the matrix A.
How can I do it in Matlab?
To verify the correct answer, just check gfrank([A;v_new]) is 5 (i.e v_new=[0 1 0 0 1]).
Note that: Two vectors uand v whose dot product is u.v=0 (i.e., the vectors are perpendicular) are said to be orthogonal.
As AVK also mentioned in the comments, v_new = [0 1 0 0 1] is not orthogonal to all rows of A.
Explanation:-
A=[1 0 0 1 0;
0 1 1 0 0;
0 0 1 1 0;
1 1 1 0 0]
For A(1,:).*v = 0 to A(4,:).*v = 0,
0 x x 0 x % elements of v so that it's orthagonal to the 1st row of A
x 0 0 x x % -------------------------------------------- 2nd row of A
x x 0 0 x % -------------------------------------------- 3rd row of A
0 0 0 x x % -------------------------------------------- 4th row of A
where 0 represents the terms which have to be 0 and x represents the terms which can be either 0 or 1.
If you look as a whole, first 4 columns of v have to be zero so that the output is orthagonal to all rows of A. The 5th column can either be zero or 1.
So,
v_new can either be: v_new = [0 0 0 0 1] or v_new = [0 0 0 0 0]
From above explanation, you can also see that [0 1 0 0 1] is not orthagonal to 2nd and 4th row of A
Solution:-
To find v_new, you can use null function as: v_new = null(A).'
which gives: v_new = [0 0 0 0 1] for which gfrank([A;v_new]) also gives 5.
Maybe this will help you see the orthogonality between two vectors in N dimension.
N=100;
B1 = ones(1,N);
B2 = -1*ones(1,N/2);
B2 = [ones(1,N/2) B2];
B2 = transpose(B2);
B3 = dot(B1,B2);
The above code generates two vectors in N dimension. To check for orthogonality just transpose one of the vectors and multiply with the other one. You should get zero if they are Orthogonal.
The example I used makes sure that I get zero indeed.
I have code like below:
N=10;
R=[1 1 1 1 1 0 0 0 0 0;1 1 1 1 1 1 1 1 1 1];
p=[0.1,0.2,0.01];
B = zeros(N , N);
B(1:N,1:N) = eye(N);
C=[B;R];
for q=p(1:length(p))
Rp=C;
for i=1:N
if(rand < p)
Rp(i,:) = 0;
end
end
end
from this code I vary the value of p. So for different value of p, i am getting different Rp. Now I want to get the total number of "1"'s from each Rp matrix. it means may be for p1 I am getting Rp1=5, for p2, Rp=4.
For example
Rp1=[1 0 0 0 0;0 1 0 0 0;0 0 0 0 0],
Rp2=[1 0 0 0 0;0 1 0 0 0;1 0 0 0 0],
Rp3=[0 0 0 0 0;0 1 0 0 0;0 0 0 0 0],
So total result will be 2,3,1.
I want to get this result.
If the matrix contains only 0 and 1 you are trying to count the nonzero values and there is a function for that called nnz
n = nnz(Rp);
As I mentioned in the comments you should replace
if(rand < p)
with
if(rand < q)
Then you can add the number of nonzero values to a vector like
r = [];
for q=p(1:length(p))
Rp=C;
for i=1:N
if(rand < p)
Rp(i,:) = 0;
end
end
r = [r nnz(Rp)];
end
Then r will contain your desired result. There are many ways to improve your code as mentioned in other answers and comments.
Assuming Rp is your matrix, then simply do one of the following:
If your matrix only contains zeros and ones
sum(Rp(:))
Or if your matrix contains multiple values:
sum(Rp(:)==1)
Note that for two dimensional matrices sum(Rp(:)) is the same as sum(sum(Rp))
I think your real question is how to save this result, you can do this by assigning it to an indexed varable, for example:
S(count) = sum(Rp(:));
This will require you to add a count variable that increases with one every step of the loop. It will be good practice (and efficient) to initialize your variable properly before the loop:
S = zeros(length(p),1);
If you need to count the 1's in any matrix M you should be able to do sum(M(:)==1)