Best way to make a random matrix subject to full rank - algorithm

I want to make a matrix k x n (k rows and n columns) that its rank is k. My idea is that I will check the current rank of matrix at each generation of column. If the current rank is small than number of current column j, I will make the column again until the rank equals current column. This is my code. However, it work very slowly (due to check rank at every step). Please help me to modify it.
function G=fullRank(k,n)
%% make matrix kxn
j=0;
while(j<n)
d=randi(k,1)
column = [ones(1,d) zeros(1,k-d)];
column = column(randperm(k));
G(:,j)=column';
%% check full rank- Modify here
if((j>=2)&(rank(full(G))<j)&&(j<=k))
%% Set current column of G to zeros
column =zeros(1,k);
G(:,j) = column';
else
j=j+1;
end
end

The probability of your matrix not being full-rank depends on how you choose the random values for its entries, but I guess it is low. In that case, you can save time checking only at the end, and generating the full matrix again if needed:
maxrank = min(k,n); %// precompute to save a little time
G = []; %// this is just to enter the while loop at least once
while rank(G)<maxrank
G = randi(k,k,n); %// replace by your procedure to generate G
end

Related

continous speech recocnition end point detection

does somebody know the algorithm for end point detection in continuous speech? because I can't find one, the existing algorithm is for isolated word, and not continuous, plis help. If may matlab source code would be helpfull
this is my algorithm
index1=[];
for i=1:length(spektral)
if abs(spektral(i))> 0.025
y(i)=spektral(i);
index1=[index1 i];
else y(i)=0;
end
end
spasi=[];
for i=2:length(index1)-1
if index1(i)>(index1(i-1)+1)
spasi=[spasi ; index1(i-1) index1(i)]; %penentuan spasi antarkata
end
end
The first loop can be omitted completely:
[row,col,val] = find(spektral>0.025);
This will output val the same as you have defined y above. Depending on the size of spektral, either row or col will contain your index1. If spektral is a column vector it will be row, if spektral is a row vector it will be col.
The second loop you can omit as well:
[row,col,val] = find(index1(2:end,:)>index1(1:end-1,:)+1);
Note that index1 will have to be either row or col as output from the first find command.
If I understand correctly, you want to have the spectral energy below the threshold to be considered as noise and want to have more than four seconds of this spectral energy below the threshold to classify it as a silence. In that case:
[row,col,val] = find(spektral<0.025);
tmp = cummin(row); % use cummin(col) if spektral is a row vector
Here I always struggle with find a short, vectorised way to check to subsequent amount of ones in the column, I'll add it when I find the solution.
You can do this with a nested while loop, but there's bound to be a vectorised way:
kk = 1;
while kk<length(tmp)-1
silence1 = 0;
while tmp(kk) = tmp(kk+1)
silence1 = silence1+1; % Sum the length of each silence
kk = kk+1;
end
silence(kk) = silence1;
end
silence(silence1==0)=[]; % Remove zero entries
TotalSilences = (sum(silence>4)); % Find the total number of silences

How can I make my code faster?

I write this code for solving problem 4- project euler, but it takes too long for giving me the answer.
Is there any trick to make it faster?
function S=Problem4(n)
tic
Interval=10^(n-1):10^(n)-1;
[Product1,Product2]=meshgrid(Interval);
Func=#(X,Y) X*Y;
Temp=cell2mat(arrayfun(Func,Product1,Product2,'UniformOutput',false));
Palindrome=#(X) all(num2str(X)==fliplr(num2str(X)));
Temp2=unique(Temp(:));
S=max(Temp2(arrayfun(Palindrome,Temp2)));
toc
end
and it takes about 39 secs.
Any help would be appreciated.
Only a partial answer here, but a big performance hit is often caused by using strings to handle numbers.
And here you have a function that even does it twice in one line!
First try to get rid of one by saving the intermediate result in a variable. If that saves a significant amount of time it is probably worth removing the other one as well.
Here is my own approach from a few years back. It is not that great, but perhaps it can inspire you.
Note that it does use num2str, but only once and on all relevant numbers at once. In your code you use arrayfun which basically uses a loop internally, and probably results in many calls to num2str.
clear
field = (100:999)'*(100:999);
field = field(:);
fieldstr = num2str(field);
idx = fieldstr(:,1) == fieldstr(:,end);
idx2 = fieldstr(:,2) == fieldstr(:,end-1);
idx3 = fieldstr(:,3) == fieldstr(:,end-2);
list = fieldstr(idx & idx2 & idx3,:);
listnum = str2num(list);
max(listnum)
From Project Euler:
Largest palindrome product
Problem 4
A palindromic number reads the same both ways. The largest palindrome made from the product of two 2-digit numbers is 9009 = 91 × 99.
Find the largest palindrome made from the product of two 3-digit numbers.
Instead of analyzing your code, I'll give you another way of doing it, which you might find useful. It makes use of vectorization, avoiding arrayfun and anonymous functions, which may be slow:
[n1, n2] = ndgrid(100:999); %// all combinations of 3-digit numbers
pr = n1(:).*n2(:); %// product of each combination
de = dec2base(pr, 10); %// decimal expression of those products
sm = pr<1e5; %// these have 5 figures: initial digit "0" should be disregarded
pa = false(1,numel(pr)); %// this will indicate if each product is palindromic or not
pa(sm) = all(de(sm,2:end) == fliplr(de(sm,2:end)), 2); %// 5-figure palindromic
pa(~sm) = all(de(~sm,:) == fliplr(de(~sm,:)), 2); %// 6-figure palindromic
result = max(pr(pa)); %// find maximum among all products indicated by pa
You can save almost half the time by avoiding duplicate products, as follows. The three new lines are marked:
[n1, n2] = ndgrid(100:999); %// all combinations of 3-digit numbers
un = n1(:)<=n2(:); %// NEW
n1 = n1(un); %// NEW
n2 = n2(un); %// NEW
pr = n1(:).*n2(:); %// product of each combination
de = dec2base(pr, 10); %// decimal expression of those products
sm = pr<1e5; %// these have 5 figures: initial digit "0" should be disregarded
pa = false(1,numel(pr)); %// this will indicate if each product is palindromic or not
pa(sm) = all(de(sm,2:end) == fliplr(de(sm,2:end)), 2); %// 5-figure palindromic
pa(~sm) = all(de(~sm,:) == fliplr(de(~sm,:)), 2); %// 6-figure palindromic
result = max(pr(pa)); %// find maximum among all products indicated by pa
Some Discussion and Solution Code
Since you are looking for the maximum palindrome, after you have collected possible product numbers with that Interval, for every possible number of digits for all the numbers you can iteratively look for the maximum possible number. Thus, with n = 3, you would have from 10000 to 998001 as the products. So, you can look for the maximum palindrome number within the 6 digit numbers first, then go for 5 digits ones and so on. The benefit with such an iterative approach would be that you can get out of the function as soon as you have the max number. Here's the code to fulfil the promises laid in the discussion -
function S = problem4_try1(n)
Interval=10^(n-1):10^(n)-1; %// Define interval definition here
prods = bsxfun(#times,Interval,Interval'); %//'# Or Use: Interval'*Interval
allnums = prods(:);
numd = ceil(log10(allnums)); %// number of digits
dig = sort(unique(numd),'descend'); %// unique digits starting from highest one
for iter = 1:numel(dig)
numd_iter = dig(iter);
numd_iter_halflen = floor(numd_iter/2);
all_crit = allnums(numd==numd_iter); %//all numbers in current iteration
all_crit_dg = dec2base(all_crit,10)-'0'; %// separate digits for a 2D array
all_curit_digits_pal = all_crit(all(all_crit_dg(:,1:numd_iter_halflen) == ...
all_crit_dg(:,end:-1:end-numd_iter_halflen+1) ,2)); %// palindrome matches
%// Find the max of palindrom matches and get out
if ~isempty(all_curit_digits_pal)
S = max(all_curit_digits_pal);
return; %// *** Get Outta Here!!
end
end
Few things about the code itself
bsxfun(#times,Interval,Interval') efficiently gets us the product values, which you have in Temp and as such this must be pretty efficient, as don't have to deal with the intermediate Product1 and Product2.
Because of the iterative nature, it must be efficient enough for higher n's, given the system can handle the pre-processing part of the calculation of the products at the start.
I encourage you to see this link (improving matlab performance), also, i recommend using a "cache/memory" funcion, when you have iterations of calculations you can store the parameters and answers so next time you have the same parameters you just return the stored answer skipping some calculations in the process.
Hope it helps someway, tell me if you have more doubts.

What is the fast way to calculate this summation in MATLAB?

So I have the following constraints:
How to write this in MATLAB in an efficient way? The inputs are x_mn, M, and N. The set B={1,...,N} and the set U={1,...,M}
I did it like this (because I write x as the follwoing vector)
x=[x_11, x_12, ..., x_1N, X_21, x_22, ..., x_M1, X_M2, ..., x_MN]:
%# first constraint
function R1 = constraint_1(M, N)
ee = eye(N);
R1 = zeros(N, N*M);
for m = 1:M
R1(:, (m-1)*N+1:m*N) = ee;
end
end
%# second constraint
function R2 = constraint_2(M, N)
ee = ones(1, N);
R2 = zeros(M, N*M);
for m = 1:M
R2(m, (m-1)*N+1:m*N) = ee;
end
end
By the above code I will get a matrix A=[R1; R2] with 0-1 and I will have A*x<=1.
For example, M=N=2, I will have something like this:
And, I will create a function test(x) which returns true or false according to x.
I would like to get some help from you and optimize my code.
You should place your x_mn values in a matrix. After that, you can sum in each dimension to get what you want. Looking at your constraints, you will place these values in an M x N matrix, where M is the amount of rows and N is the amount of columns.
You can certainly place your values in a vector and construct your summations in the way you intended earlier, but you would have to write for loops to properly subset the proper elements in each iteration, which is very inefficient. Instead, use a matrix, and use sum to sum over the dimensions you want.
For example, let's say your values of x_mn ranged from 1 to 20. B is in the set from 1 to 5 and U is in the set from 1 to 4. As such:
X = vec2mat(1:20, 5)
X =
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
vec2mat takes a vector and reshapes it into a matrix. You specify the number of columns you want as the second element, and it will create the right amount of rows to ensure that a proper matrix is built. In this case, I want 5 columns, so this should create a 4 x 5 matrix.
The first constraint can be achieved by doing:
first = sum(X,1)
first =
34 38 42 46 50
sum works for vectors as well as matrices. If you have a matrix supplied to sum, you can specify a second parameter that tells you in what direction you wish to sum. In this case, specifying 1 will sum over all of the rows for each column. It works in the first dimension, which is the rows.
What this is doing is it is summing over all possible values in the set B over all values of U, which is what we are exactly doing here. You are simply summing every single column individually.
The second constraint can be achieved by doing:
second = sum(X,2)
second =
15
40
65
90
Here we specify 2 as the second parameter so that we can sum over all of the columns for each row. The second dimension goes over the columns. What this is doing is it is summing over all possible values in the set U over all values of B. Basically, you are simply summing every single row individually.
BTW, your code is not achieving what you think it's achieving. All you're doing is simply replicating the identity matrix a set number of times over groups of columns in your matrix. You are actually not performing any summations as per the constraint. What you are doing is you are simply ensuring that this matrix will have the conditions you specified at the beginning of your post to be enforced. These are the ideal matrices that are required to satisfy the constraints.
Now, if you want to check to see if the first condition or second condition is satisfied, you can do:
%// First condition satisfied?
firstSatisfied = all(first <= 1);
%// Second condition satisfied
secondSatisfied = all(second <= 1);
This will check every element of first or second and see if the resulting sums after you do the above code that I just showed are all <= 1. If they all satisfy this constraint, we will have true. Else, we have false.
Please let me know if you need anything further.

Matlab - if exists a faster way to assign values to big matrix?

I am a new student learning to use Matlab.
Could anyone please tell me is there a faster way possibly without loops:
to assign for each row only two values 1, -1 into different positions of a big sparse matrix.
My code to build a bimatrix or bibimatrix for the MILP problem of condition :
f^k_{ij} <= y_{ij} for every arc (i,j) and all k ~=r; in a multi-commodity flow model.
Naive approach:
bimatrix=[];
% create each row and then add to bimatrix
newrow4= zeros(1,n*(n+1)^2);
for k=1:n
for i=0:n
for j=1: n
if j~=i
%change value of some positions to -1 and 1
newrow4(i*n^2+(j-1)*n+k)=1;
newrow4((n+1)*n^2+i*n+j)=-1;
% add to bimatrix
bimatrix=[bimatrix; newrow4];
% change newrow4 back to zeros row.
newrow4(i*n^2+(j-1)*n+k)=0;
newrow4((n+1)*n^2+i*n+j)=0;
end
end
end
end
OR:
% Generate the big sparse matrix first.
bibimatrix=zeros(n^3 ,n*(n+1)^2);
t=1;
for k=1:n
for i=0:n
for j=1: n
if j~=i
%Change 2 positions in each row to -1 and 1 in each row.
bibimatrix(t,i*n^2+(j-1)*n+k)=1;
bibimatrix(t,(n+1)*n^2+i*n+j)=-1;
t=t+1
end
end
end
end
With these above code in Matlab, the time to generate this matrix, with n~12, is more than 3s. I need to generate a larger matrix in less time.
Thank you.
Suggestion: Use sparse matrices.
You should be able to create two vectors containing the column number where you want your +1 and -1 in each row. Let's call these two vectors vec_1 and vec_2. You should be able to do this without loops (if not, I still think the procedure below will be faster).
Let the size of your matrix be (max_row X max_col). Then you can create your matrix like this:
bibimatrix = sparse(1:max_row,vec_1,1,max_row,max_col);
bibimatrix = bibimatrix + sparse(1:max_row, vec_2,-1,max_row,max_col)
If you want to see the entire matrix (which you don't, since it's huge) you can write: full(bibimatrix).
EDIT:
You may also do it this way:
col_vec = [vec_1, vec_2];
row_vec = [1:max_row, 1:max_row];
s = [ones(1,max_row), -1*ones(1,max_row)];
bibimatrix = sparse(row_vec, col_vec, s, max_row, max_col)
Disclaimer: I don't have MATLAB available, so it might not be error-free.

choosing row m from two matrices at random

I have two m*n matrices, A and P. I want to randomly choose the same 3 rows from both matrices, e.g. rows m, m+1, m+2 are picked from both matrices. I want to be able to make the calculation U=A-P on the selected subset (i.e. Usub-Psub), rather than before the selection. So far I have only been able to select rows from one matrix, without being able to match it to the other. The code I use for this is:
A=[0,1,1,3,2,4,4,5;0,2,1,1,3,3,5,5;0,3,1,1,4,4,2,5;0,1,1,1,2,2,5,5]
P=[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,0,0,0]
U=A-P
k = randperm(size(U,1));
Usub = U(k(1:3),:);
I would first create a function that returned a submatrix that had only three rows in it that takes an integer as the first of the three row. Then i'd do something like this:
m = number of rows;
randomRow = rand() % m;
U = A.sub(randomRow) - P.sub(randomRow);

Resources