I am going to find efficiently all loops with length 4 in a large graph.I have the following code for this purpose but it is not efficient.
[rows, cols, s] = find(Mystructure);
for i = 1:size(cols,1)
a = rows(i);
b = cols(i);
C=cols(find(rows==b));
for j=1:size(C)
c=C(j);
D=cols(find(and(rows==c, rows~=a)));
for k=1:size(D)
d=D(k);
if(d~=a && d~=b)
if(find(and(rows==d, cols==a)))
FourStructure=[FourStructure;a b c d] ;
end
end
end
end
end
Mystructure is a sparse matrix representing my graph. Mystructure(i,j) is one if and only if i,j be connected.
Related
In model predictive control, an optimization problem is solved at every time instant and it is very common to write down the matrices in a compact form. Without going into the details of the optimization problem, suppose I have matrices and . I need to compute the matrices and defined as
Note that N_p is called "prediction horizon" and it is not the order of matrix A. How can I compute these matrices in a fast and efficient way? In Matlab, I have done the following, but maybe there is a more efficient way to compute these matrices:
A_cal = zeros(length(A)*Np, length(A)); %calligraphic A matrix
B_cal = zeros(size(B,1)*Np, size(Bd,2)*Np); %calligraphic B matrix
temp = eye(size(A));
for j = 1:Np
A_cal(1+(j-1)*length(A):j*length(A),:)= temp;
if j > 1
%The current row is obtained as shift of the previous row, and only the block in the first column is computed
B_cal(1+(j-1)*size(B,1):j*size(B,1),:) = circshift(B_cal(1+(j-2)*size(B,1):(j-1)*size(B,1),:),size(B,2),2);
B_cal(1+(j-1)*size(B,1):j*size(B,1),1:size(B,2)) = temp_prev*B_cent;
end
temp_prev = temp; %this variable contains A^(j-1)
temp = temp * A_cent; %use temp variable to speed up the matrix power computation
end
I assume you already solved your problem, but here is the code from my exercises sheet, creating your matrices.
S_x being the first matrix.
function S_x = compute_Sx(A,N)
S_x = eye(size(A));
for i=1:N
S_x = [S_x;A^i];
end
end
function S_u = compute_Su(A,B,N)
S_u = zeros(size(A,1)*N,size(B,2)*N);
for i=1:N
S_u = S_u + kron(diag(ones(N-i+1,1),-i+1),A^(i-1)*B);
end
S_u = [zeros(size(A,1),size(B,2)*N);S_u];
end
Best Regards
I have a small logical array (A) of size 256x256x256 with an unknown shape of ones somewhere in the array. Also there is a smaller double array (se) of size 13x13x13. In se there is a defined cube of logical ones in the middle of the array (se).
I need to run over every logical element in A and for each logical one in A the smaller array se needs to add its ones to A. Meaning dilating the shape of A by se.
Here is what I got so far. It works, but is of very poor performance in respect to speed.
Does anyone has a suggestion of how to speed up this coding task?
[p, q, r] = size(se);
[m, n, o] = size(A);
temp = zeros(m, n, o);
for i = 1:m
for j = 1:n
for k = 1:o
if img_g(i, j, k) == 1
for s = 1:p
for t = 1:q
for u = 1:r
if se(s, t, u) == 1
c = i + s;
d = j + t;
e = k + u;
temp(c, d, e) = 1;
end
end
end
end
end
end
end
end
B = temp;
I am very grateful for any help and suggestions that improve my programming skills.
dependent on the processor you're using, you can at least use "parfor" for the outer loop (first loop).
this enables parallel computing and accelerates your performance by the number of physical kernels your processor got.
I'm not 100% sure this does what you're asking (as I'm not completely clear on what your code does), but perhaps the methodology will give some inspiration.
I've not generated a "logical" A, but a random one, and I've set a cube inside equal to 1. Similar for se. I use meshgrid to get arrays corresponding to the indices, and use a mask of logical indexing. (perhaps my mask is what you have for A in the first place?)
A = rand(255,255,255);
A(40:50, 23:33, 80:100) = 1;
mask = (A==1);
[I,J,K] = meshgrid(1:255);
se = rand(13,13,13);
se(4:6, 3:7, 2:8) = 1;
se_mask = (se==1);
[se_I, se_J, se_K] = meshgrid(1:13);
Here I'm assuming that the cube in A is far enough from any edge (say 13 spaces) so we wont get c, d or e larger than 255.
I've flattened mask into a row vector so find gives a single index ii we can use to refer to any point in A, then the original i,j and k indices are in I(ii), J(ii), and K(ii) respectively. Similar for se_I etc.
temp = zeros(255, 255, 255);
for ii=find(mask(:).')
for jj=find(se_mask(:).')
c = I(ii) + se_I(jj);
d = J(ii) + se_J(jj);
e = K(ii) + se_K(jj);
temp(c,d,e) = 1;
end % for
end % for
The matrices I, J, K, se_I, se_J and se_K are regular, so if making/storing these becomes a bottleneck you can write functions to replace them. Matrix temp might be very sparse depending on the size of your cubes of ones, so you could look into using sparse.
I've not compared the timings against your solution.
I have the problem when I compute in a matrix. This problem is about the speed of computation.
I have a matrix of binary image (f), I find conected component by bwlabel in matlab. [L num]=bwlabel(f);
after that base on some property I found a vector p that include some value of L that I need to remove. this is my code and explanation
function [f,L] = clear_nontext(f,L,nontext)
% p is a vector include a lot of value we need to remove
p=find(nontext(:)~=0);
% example p= [1 2 9 10 100...] that mean we need to find in L matrix where get the value =1,2,9,10,100..] and remove it
[a b]=size(L);
g=zeros(a,b);
for u=1:length(p)
for i=1:a
for j=1:b
if L(i,j)==p(u)
g(i,j)=1;
%L(i,j)=500000;
f(i,j)=0;
end
end
end
end
end
When I use this way, program run but it is so slow, because with one value of p we need to check all value in matrix f (or L) again. So I need another way to run it faster. Could you help me?
Thank you so much
Generally, MATLAB performs matrix operations (or index operations) faster then loops.
You can try the following:
g(ismember(L,p)) = 1;
f(ismember(L,p)) = 1;
EDIT:
I was curious so I ran a little test:
L = round(20*randn(10000,10000));
f = L;
p = 1:5;
[a b]=size(L);
g=zeros(a,b);
tic;
for u=1:length(p)
for i=1:a
for j=1:b
if L(i,j)==p(u)
g(i,j)=1;
f(i,j)=0;
end
end
end
end
toc
for which I got:
Elapsed time is 38.960842 seconds.
When I tried the following:
tic;
g(ismember(L,p)) = 1;
f(ismember(L,p)) = 0;
toc
I got
Elapsed time is 5.735137 seconds.
I've created a function (name it MyFunction) which, given a matrix A, outputs two matrices B and C i.e. [B C] = MyFunction(A).
I'm trying to create another function which, when given a matrix A, will calculate MyFunction(A) and then calculate MyFunction(B) = [D E] and MyFunction(C) = [F G], and then calculate MyFunction(D), MyFunction(E), MyFunction(F) and MyFunction(G), and so on, until the matrices it outputs start to repeat. I know this process necessarily terminates.
I'm really having difficulty constructing this code. Any advice would be really appreciated.
I think what you're trying to do is binary tree recursion. It's hard to give a good solution without knowing more about the problem, especially without knowing what you want as the output of this process.
I whipped this up to give an example of how you could do this. It's not necessarily the most efficient because it stores all of the results at every step. Given an input matrix A, it calculates a 2-output function [B, C] = MyFunction(A) and looks for either isequal(A, B) or isequal(A, C). When that occurs, it outputs the depth of the tree at that point, i.e. how many iterations had to occur before there was a repetition. The bit with global variables is just so that I could do a simple example with an easy fixed point (the k'th iteration is just A^k). It will iterate a maximum of 10 times.
function depth = myRecursor(A)
global A_orig;
A_orig = A;
depth = 1;
max_depth = 10;
pvs_level = cell(1);
pvs_level{1} = A;
while depth < max_depth,
this_level = cell(2*length(pvs_level), 1);
for ix = 1 : length(pvs_level),
[B, C] = MyFunction(pvs_level{ix})
if isequal(B, A) || isequal(C, A),
return;
end
this_level{2*ix - 1} = B;
this_level{2*ix} = C;
end
depth = depth + 1;
pvs_level = this_level;
end
function [B, C] = MyFunction(A)
global A_orig;
B = A_orig*A;
C = 2*A;
So, for example myRecursor(eye(2)) gives 1 (duh) and myRecursor([0 1; 1 0]) gives 2.
EDIT: rewritten wrong alg
function [list] = newFunction(A) % returns all matrix generated matrix
list{1}=A;
done=0;
ii = 1;
while(~done)
[B C] = myFunction(list{ii});
list = list{list{:}, B, C};
for jj=1:numel(list)-2
if(all(all(list{jj}==B)) || all(all(list{jj}==C)))
done = 1;
end
end
ii=ii+1;
end
end
UPDATE: a more general way to handle an unknown number of outputs is to modify myFunction so that it outputs all matrices within a single cell vector. This way you can concatenate list this way:
[newMat] = myFunctions(list{ii}); % where newMat={B,C,...}
list = {list{:}, newMat{:}}; % or list=cat(2,list,newMat)
for jj=1:numel(list)-numel(newMat)
for nn=1:numel(newMat) % checking for repetitions
if(all(all(list{jj}==newMat{nn})))
done=1;
end
end
end
I think you should use cells:
function [B]=Myfunction(A)
B=cell(1,numel(A)*2);
for n=1:numel(A)
B{n}=func1(A{n}) %%% put some processing here
B{numel(A)+n}=func2(A{n}) %%% put some other processing here
end
end
I was wondering if there is a way of speeding up (maybe via vectorization?) the conditional filling of huge sparse matrices (e.g. ~ 1e10 x 1e10). Here's the sample code where I have a nested loop, and I fill in a sparse matrix only if a certain condition is met:
% We are given the following cell arrays of the same size:
% all_arrays_1
% all_arrays_2
% all_mapping_arrays
N = 1e10;
% The number of nnz (non-zeros) is unknown until the loop finishes
huge_sparse_matrix = sparse([],[],[],N,N);
n_iterations = numel(all_arrays_1);
for iteration=1:n_iterations
array_1 = all_arrays_1{iteration};
array_2 = all_arrays_2{iteration};
mapping_array = all_mapping_arrays{iteration};
n_elements_in_array_1 = numel(array_1);
n_elements_in_array_2 = numel(array_2);
for element_1 = 1:n_elements_in_array_1
element_2 = mapping_array(element_1);
% Sanity check:
if element_2 <= n_elements_in_array_2
item_1 = array_1(element_1);
item_2 = array_2(element_2);
huge_sparse_matrix(item_1,item_2) = 1;
end
end
end
I am struggling to vectorize the nested loop. As far as I understand the filling a sparse matrix element by element is very slow when the number of entries to fill is large (~100M). I need to work with a sparse matrix since it has dimensions in the 10,000M x 10,000M range. However, this way of filling a sparse matrix in MATLAB is very slow.
Edits:
I have updated the names of the variables to reflect their nature better. There are no function calls.
Addendum:
This code builds the matrix adjacency for a huge graph. The variable all_mapping_arrays holds mapping arrays (~ adjacency relationship) between nodes of the graph in a local representation, which is why I need array_1 and array_2 to map the adjacency to a global representation.
I think it will be the incremental update of the sparse matrix, rather than the loop based conditional that will be slowing things down.
When you add a new entry to a sparse matrix via something like A(i,j) = 1 it typically requires that the whole matrix data structure is re-packed. The is an expensive operation. If you're interested, MATLAB uses a CCS data structure (compressed column storage) internally, which is described under the Data Structure section here. Note the statement:
This scheme is not effcient for manipulating matrices one element at a
time
Generally, it's far better (faster) to accumulate the non-zero entries in the matrix as a set of triplets and then make a single call to sparse. For example (warning - brain compiled code!!):
% Inputs:
% N
% prev_array and next_array
% n_labels_prev and n_labels_next
% mapping
% allocate space for matrix entries as a set of "triplets"
ii = zeros(N,1);
jj = zeros(N,1);
xx = zeros(N,1);
nn = 0;
for next_label_ix = 1:n_labels_next
prev_label = mapping(next_label_ix);
if prev_label <= n_labels_prev
prev_global_label = prev_array(prev_label);
next_global_label = next_array(next_label_ix);
% reallocate triplets on demand
if (nn + 1 > length(ii))
ii = [ii; zeros(N,1)];
jj = [jj; zeros(N,1)];
xx = [xx; zeros(N,1)];
end
% append a new triplet and increment counter
ii(nn + 1) = next_global_label; % row index
jj(nn + 1) = prev_global_label; % col index
xx(nn + 1) = 1.0; % coefficient
nn = nn + 1;
end
end
% we may have over-alloacted our triplets, so trim the arrays
% based on our final counter
ii = ii(1:nn);
jj = jj(1:nn);
xx = xx(1:nn);
% just make a single call to "sparse" to pack the triplet data
% as a sparse matrix object
sp_graph_adj_global = sparse(ii,jj,xx,N,N);
I'm allocating in chunks of N entries at a time. Assuming that you know alot about the structure of your matrix you might be able to use a better value here.
Hope this helps.