create vectors using exponent/power for numbers using prime powers - matlab

I am trying to create vectors for every number up to n by just using the exponents of the prime numbers, using prime vector PV=[2 3 5 7 11 13 17 19 23 29] to recognize each number and store these vectors for later calculations. My PVE=[k k k k k k k k k k x], with k being the exponents corrisponding to PV, and x is the exponent of any prime that PV does not divide, so x will always be 0 or 1 because my n is 960=(31^2)-1. So if any number in this set divides some number 9, for instance the vector exponent of 9 would be [0 2 0 0 0 0 0 0 0 0 0] as 3^2 is 9. and the vector for 22 would be [1 0 0 0 1 0 0 0 0 0 0] and this is 2*11=22. so every "numba" as in my program from 2 to n would have a prime vector exponent (PVE). This comes from the fundamental theorem of arithmetic that every number can be expressed as the product of primes, and it is unique.
Could you please look at my program to see what I am doing wrong to get the exponents.
Program:
n=960
for numba=2:n
for c=2:numba-1
if numba==2
c=2
if mod(numba,c)~=0
numba=p
end
end
end
end
for k=1:9
PVEC=[2^k 3^k 5^k 7^k 11^k 13^k 17^k 19^k 23^k 29^k]
if p>29
if mod(numba,PVEC)==0
max(PVEC,k) & PVE==[k k k k k k k k k k 0]
if mod(numba,PVE)~=0
PVE=[0 0 0 0 0 0 0 0 0 0 1]
end
end
end
end

You can compute PVE for each numba in one line, using factors and histc:
PVE = histc(factor(numba),[PV inf])
Example:
>> PV = [2 3 5 7 11 13 17 19 23 29];
>> numba = 22;
>> PVE = histc(factor(numba),[PV inf])
PVE =
1 0 0 0 1 0 0 0 0 0 0
>> numba = 9;
>> PVE = histc(factor(numba),[PV inf])
PVE =
0 2 0 0 0 0 0 0 0 0 0

I don't quite understand what you are trying to do in your first loop, but if I were you, I would use recursion to get an exponent. Something like this...
function [ expo ] = get_exponent( p, num, depth )
% return the exponent
% p: prime number
% num: number to be analyzed
% depth: depth of the recursion
if p==1,
error ('Do not use 1 for p!!')
end
if mod(num,p) == 0,
depth = depth+1;
expo = get_exponent(p, num/p, depth);
else
expo = depth;
end
end
This get_exponent function returns the exponent for some number num of some prime p. For example,
>> get_exponent(5,325,0)
ans =
2
>> get_exponent(13,325,0)
ans =
1
Use this function in your second loop to get exponent of each prime.

Related

Faster way to transpose each row of a matrix and multiply the resulting vector by some other matrix?

I have an input matrix X with dimensions N_rows x N_cols. I also have a sparse, tridiagonal matrix M which is square of size N_rows x N_rows. These are created as follows:
N_rows = 3;
N_cols = 6;
X = rand(N_rows,N_cols);
mm = 10*ones(N_cols,1); % Subdiagonal elements
dd = 20*ones(N_cols,1); % Main diagonal elements
pp = 30*ones(N_cols,1); % Superdiagonal elements
M = spdiags([mm dd pp],-1:1,N_cols,N_cols);
and look like the following:
>> X
X =
0.4018 0.1233 0.4173 0.9448 0.3377 0.1112
0.0760 0.1839 0.0497 0.4909 0.9001 0.7803
0.2399 0.2400 0.9027 0.4893 0.3692 0.3897
full(M)
ans =
2 3 0 0 0 0
1 2 3 0 0 0
0 1 2 3 0 0
0 0 1 2 3 0
0 0 0 1 2 3
0 0 0 0 1 2
I would like to take each row of X, and do a matrix multiplication with M, and piece the obtained rows back together to obtain an output Y. At the moment, I achieve this successfully with the following:
Y = (M*X.').';
The example above is for a 3x6 matrix for X, but in reality I need to do this for a matrix with dimensions 500 x 500, about 10000 times, and the profiler says that this operation in the bottleneck in my larger code. Is there a faster way to do this row-by-row matrix multiplication multiplication?
On my system, the following takes around 20 seconds to do this 10000 times:
N_rows = 500;
N_cols = 500;
X = rand(N_rows,N_cols);
mm = 10*ones(N_cols,1); % Subdiagonal elements
dd = 20*ones(N_cols,1); % Main diagonal elements
pp = 30*ones(N_cols,1); % Superdiagonal elements
M = spdiags([mm dd pp],-1:1,N_cols,N_cols);
tic
for k = 1:10000
Y = (M*X.').';
end
toc
Elapsed time is 18.632922 seconds.
You can use X*M.' instead of (M*X.').';. This saves around 35% of time on my computer.
This can be explained because transposing (or permuting dimensions) implies rearranging the elements in the internal (linear-order) representation of the matrix, which takes time.
Another option is using conv2:
Y = conv2(X, [30 20 10], 'same');
Explanation:
There is a tridiagonal matrix that all elements on each diagonal are identical to each other:
M =
2 3 0 0 0 0
1 2 3 0 0 0
0 1 2 3 0 0
0 0 1 2 3 0
0 0 0 1 2 3
0 0 0 0 1 2
Suppose you want to multiply the matrix by a vector:
V = [11 ;12 ;13 ;14 ;15 ;16];
R = M * V;
Each element of the vector R is computed by sum of products of each row of M by V:
R(1):
2 3 0 0 0 0
11 12 13 14 15 16
R(2):
1 2 3 0 0 0
11 12 13 14 15 16
R(3):
0 1 2 3 0 0
11 12 13 14 15 16
R(4):
0 0 1 2 3 0
11 12 13 14 15 16
R(5):
0 0 0 1 2 3
11 12 13 14 15 16
R(6):
0 0 0 0 1 2
11 12 13 14 15 16
It is the same as multiplying a sliding window of [1 2 3] by each row of M. Basically convolution applies a sliding window but first it reverses the direction of window so we need to provide the sliding window in the reversed order to get the correct result. Because of that I used Y = conv2(X, [30 20 10], 'same'); instead of Y = conv2(X, [10 20 30], 'same');.

How to permute elements of a vector by another vector to obtain a matrix of permutations

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

A matlab code I don't understand

I don't understand what does mean (1:65536 < wthresh) in the command below :
cw = reshape(b(:)' .* (1:65536 < threshold), 256, 256);
b is an image of size 256x256 and 65536=256x256. I only know commands like this one:
cw = reshape(b(:)' .* (b < threshold), 256, 256);
meaning we keep only pixels of b that are smaller than 'threshold'.
Just find out with easy examples:
>> (1:10<3)
ans =
1 1 0 0 0 0 0 0 0 0
This produces a vector where the first 2 elements are set to 1 while the rest are 0.
>> b=1:10
b =
1 2 3 4 5 6 7 8 9 10
>> b.*(1:10<3)
ans =
1 2 0 0 0 0 0 0 0 0
This does an element-wise multiplication with vector b. So basically the first threshold-1 elements are kept, while the rest are set to 0. reshape will rearrange the vector to a 256 x 256 matrix again. Since I don't know the expected output, I cannot judge if this is the desired behavior, or if it is a bug in your code.

Check neighbour pixels Matlab

I have a A which is 640x1 cell. where the value of each cell A(i,1) varies from row to row, for example A(1,1) =[], while A(2,1)=[1] and A(3,1)=[1,2,3].
There is another matrix B of size 480x640, where the row_index (i) of vector A corresponds to the col_index of matrix B. While the cell value of each row in vector A corresponds to the row_index in matrix B. For example, A(2,1)=[1] this means col_2 row_1 in matrix B, while A(3,1)=[1,2,3] means col_3 rows 1,2&3 in matrix B.
What I'm trying to do is to for each non-zero value in matrix B that are referenced from vector A, I want to check whether there are at least 4 other neighbors that are also referenced from vector A. The number neighbors of each value are determined by a value N.
For example, this is a part of matrix B where all the zeros"just to clarify, as in fact they may be non-zeros" are the neighbors of pixel X when N=3:
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 X 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
As shown, because N=3, all these zeros are pixel X's neighbors. So if more than 4 neighbor pixels are found in vector A then do something e.g G=1 if not then G=0;
So if anyone could please advise. And please let me know if any more clarification is needed.
The first thing I would do is to convert your cell of indices A to a logic matrix Amat. This makes it easier to check how many neighbours are included in A.
Here is a solution that uses this conversion. I hope the comments are enough to make it understandable.
clear all
clc
nCols = 7;
nRows = 6;
N = 3; %// Number of neighbours
M = 4; %// Minimum number of wanted connections
%// Create cell of indices A
A = cell(nCols,1);
A{1} = [];
A{2} = 1;
A{3} = [1 2 3];
A{4} = [2 5];
A{5} = 3;
A{6} = [3 5];
A{7} = [1 4 6];
%// Generate radom data B
%// (There is a 50% probability for each element of B to be zero)
Bmax = 17;
B = (randi(2,nRows,nCols)-1).*(randi(Bmax,nRows,nCols));
%// Convert the cell A to a logic matrix Amat
Amat = zeros(size(B));
for ii = 1:nCols
Amat(A{ii},ii) = 1;
end
A
B
Amat
for ii = 1:nCols
for jj = A{ii}
if B(jj,ii)>0
%// Calculate neighbour indices with a lower bound of 1
%// and an upper bound of nCols or nRows
col_lim_low = max(1,ii-N);
col_lim_high = min(nCols,ii+N);
row_lim_low = max(1,jj-N);
row_lim_high = min(nRows,jj+N);
%// Get the corresponding neighbouring-matrix from Amat
A_neighbours = ...
Amat(row_lim_low:row_lim_high,col_lim_low:col_lim_high);
%// Check the number of neighbours against the wanted number M
if sum(A_neighbours(:)) > 1 + M
%# do something
fprintf('We should do something here at (%d,%d)\n',jj,ii)
end
end
end
end
The following is a printout from one run of the code.
A =
[]
[ 1]
[1x3 double]
[1x2 double]
[ 3]
[1x2 double]
[1x3 double]
B =
1 5 0 0 11 0 16
0 13 13 0 0 0 9
0 0 0 5 0 0 0
3 8 16 16 0 2 12
0 0 5 0 9 9 0
12 13 0 6 0 15 0
Amat =
0 1 1 0 0 0 1
0 0 1 1 0 0 0
0 0 1 0 1 1 0
0 0 0 0 0 0 1
0 0 0 1 0 1 0
0 0 0 0 0 0 1
We should do something here at (1,2)
We should do something here at (2,3)
We should do something here at (5,6)
We should do something here at (4,7)
Since you have a one-to-one correspondence between A and B, there is no need to work on A. B is a logical matrix (0 if not referenced in A, 1 if referenced). You can therefore apply a simple filter2 function counting the number of active neighbors within the 8 closest elements.
Here is the code
B = rand(10,10); %generate binary matrix
h = [1 1 1;1 0 1;1 1 1]; %filter to be applied
filter2(h,B,'same')>=4 & B>0 %apply filter on B, count minimum of 4 neighbors, if only B>1
EDIT
To transform a cell array B into binary presence (0=empty, 1=not empty), use of cellfunis straightforward
B = ~cellfun(#isempty,B);
And see Armo's response to your previous question for how to create B based on A.

Creating an m by n matrix of 0s and 1s from m-sized vector of column indexes

I have a m-dimensional vector of integers ranging from 1 to n. These integers are column indexes for m × n matrix.
I want to create a m × n matrix of 0s and 1s, where in m-th row there's a 1 in the column that is specified by m-th value in my vector.
Example:
% my vector (3-dimensional, values from 1 to 4):
v = [4;
1;
2];
% corresponding 3 × 4 matrix
M = [0 0 0 1;
1 0 0 0;
0 1 0 0];
Is this possible without a for-loop?
Of course, that's why they invented sparse matrices:
>> M = sparse(1:length(v),v,ones(length(v),1))
M =
(2,1) 1
(3,2) 1
(1,4) 1
which you can convert to a full matrix if you want with full:
>> full(M)
ans =
0 0 0 1
1 0 0 0
0 1 0 0
Or without sparse matrix:
>> M = zeros(max(v),length(v));
>> M(v'+[0:size(M,2)-1]*size(M,1)) = 1;
>> M = M'
M =
0 0 0 1
1 0 0 0
0 1 0 0
Transposition is used because in matlab arrays are addressed by columns
In Octave, at least as of 3.6.3, you can do this easily using broadcasting:
M = v==1:4