How to make this for loop shows a graph every iteration? - matlab

General idea
I have been working on a linear algebra project, in which the idea is to test if a given set of vectors (a matrix) is linearly dependent/independent. For this the next program receives a matrix named value (user input/MxN), and make a first pass for the criterion (this part has no problems) next if the vectors are linearly dependent it must test if between the inner vectors there is some LI/LD subset, for this it starts iterating making permutations of the rows and making the criterion for it, if this results in LI subset, it must graph the vectors and the space formed by the vectors. Even when the size of the initial matrix is MxN, the matrix is usually expected to be 2 or 3 columns, R2 or R3).
Problem
In the second pass once the system is marked as linearly dependent, the system overlaps the graphics in the same windows , the desired output would be to make a first pass and if the system is LD show the a initial graph and later start graphing in separated windows the graphs of the permuted matrix formed.
NewMatrix iterates over the original "value" matrix and keeps forming the permutations of rows/vector to check the criterion again (it does, but in the same window). Note that the initial matrix "value" is defined by the user and is supposed to be already entered at the start point of the code showed.
Code
RangS=rank(R) //LI or ld criterion
[r, c] = size(value)
if (rank(value))==r
set(handles.text3,'String',('System>LI'));
figure(3);
hold on;
z = zeros(size(value, 1), 1);
quiver3(z, z, z, value(:, 1), value(:, 2), z, 0);
grid on
view(45, 45);
s=sum(value);
quiver3(0,0,0,s(1),s(2),0,'r');
points=[X' Y'];
else
set(handles.text3,'String',('System>LD'));
figure(3); //this graph should be done apart
hold on;
z = zeros(size(value, 1), 1);
quiver3(z, z, z, value(:, 1), value(:, 2), z, 0);
grid on
view(45, 45);
points=[X' Y'];
for jj = 1:size(value,1)-1 //here starts permuting vectors>credits to MikeLimaOscar
for kk = jj+1:size(value,1)
NewMatrix= value([jj,kk],:)
F=rref(NewMatrix);
RangS=rank(R) //the same criterion applied to the permutated matrices
[r, c] = size(NewMatrix)
if (rank(NewMatrix))==r
set(handles.text3,'String',('Subsystem :LI'));
figure(3); there should be one graph for every permutated matrix
hold on;
z = zeros(size(NewMatrix, 1), 1);
quiver3(z, z, z, NewMatrix(:, 1), NewMatrix(:, 2), z, 0);
grid on
view(45, 45);
s=sum(NewMatrix);
quiver3(0,0,0,s(1),s(2),0,'r');
points=[X' Y'];
else
set(handles.text3,'String',('Subsystem:LD'));
figure(3);
hold on;
z = zeros(size(NewMatrix, 1), 1);
quiver3(z, z, z, NewMatrix(:, 1), NewMatrix(:, 2), z, 0);
grid on
view(45, 45);
points=[X' Y'];
end
end
end
end

You're plotting all the graphs on the same window [figure(3)].
Providing Different arguments to figure can solve the problem.
Specific index for every window
Permutation(jj) |Permutation 1 | Permutation 2 | Permutation 3
____________________________________________________________________
|[1]submatrix 1 | [4]submatrix 1 |[6]submatrix 1
submatrix(kk) |[2]submatrix 2 | [5]submatrix 2 |[7]submatrix 2
|[3]submatrix 3 | |[8]submatrix 3
| | |[9]submatrix 4
____________________________________________________________________
Last index | 3 | 5 | 9
____________________________________________________________________
The indices in brackets will be used as figure argument
Permutation 1, just use submatrix indices kk, index_1 = kk
Permutation 2, use submatrix indices kk and the Last index submatrices from permutation 1
index_2 = Last index(Permutation 1) + kk
Permutation 3, use submatrix indices kk and the Last index submatrices from permutation 2
index_3 = Last index(Permutation 2) + kk
Generalization, a part from the first permutation, the index in nth Permutation is
index_n = Last index(Permutation n-1)) + kk
For the given question total of submatrices for a given Permutation jj can be computed as
total(Permutation jj) = numel(jj+1:size(value,1))
Please read through the comments
% Check if the entire matrix is linear independent or not
if LI
% Linear independent
% Plot the graph in window #1
figure(1)
else
% Linear dependent
% Plot the graph in window #1
figure(1)
% Starting index for next Permutation
Last_index = 0;
% Figure() argument initialization
index = 0;
% Permutation begins here
for jj = 1:size(value,1)-1
% submatrices for a given permutation jj begins here
for kk = jj+1:size(value,1)
% Check if submatrix is linear independent or not
if submatrix(kk) from permutation (jj) is LI
% Linear independent
% Plot the graph in window #index
index = Last_index + kk
figure(index)
else
% Linear dependent
% Plot the graph in window #index
index = Last_index + kk
figure(index)
end
% End of checking if submatrix is linear independent or not
end
% Update last index for the next permutation starting index
Last_index = Last_index + numel(jj+1:size(value,1))
% End of submatrices for a given permutation jj
end
% End of Permutation
end
% End of checking if the entire matrix is linear independent or not

Related

Generating random matrix in MATLAB

I would like to generate 100 random matrices A=[a_{ij}] of size 6 by 6 in (0, 9) using matlab programming satisfying the following properties:
1. multiplicative inverse: i.e., a_{ij}=1/a_{ji} for all i,j=1,2,...,6.
2. all entries are positive: i.e., a_{ij}>0 for all i,j=1,2,...,6.
3. all diagonal elements are 1: i.e., a_{ii}=1 for all i=1,2,..,6.
4. transitive: i.e., a_{ih}*a_{hj}=a_{ij} for all i,j,h=1,2,...,6.
So far, I tried to use a matlab function rand(6)*9. But, I got wrong matrices. I was wondering if anyone could help me?
Here is my matlab code:
clc; clear;
n=6;
m=0;
for i=1:n
for j=1:n
for h=1:n
while m<100 % generate 100 random matrices
A=rand(n)*9; % random matrix in (0,9)
A(i,j)>0; % positive entries
A(i,j)==1/A(j,i); % multiplicative inverse
A(i,h)*A(h,j)==A(i,j); % transitive
if i==j && j==h
A(i,j)==1; % diagonal elements are 1
break;
end
m=m+1;
M{m}=A
end
end
end
end
M{:}
clear; clc
M = cell(1, 100); % preallocate memory
% matrix contains both x & 1/x
% we need a distribution whose multiplication with its inverse is uniform
pd = makedist('Triangular', 'a', 0, 'b', 1, 'c', 1);
for m=1:100 % 100 random matrices
A = zeros(6); % allocate memory
% 5 random numbers for 6x6 transitive random matrix
a = random(pd, 1, 5);
% choose a or 1/a randomly
ac = rand(1, 5) < 0.5;
% put these numbers above the diagonal
for i=1:5
if ac(i)
A(i, i+1) = a(i);
else
A(i, i+1) = 1 / a(i);
end
end
% complete the transitivity going above
for k=flip(1:4)
for i=1:k
A(i, i-k+6) = A(i, i-k+5) * A(i-k+5, i-k+6);
end
end
% lower triangle is multiplicative inverse of upper triangle
for i=2:6
for j=1:i-1
A(i,j) = 1 / A(j,i);
end
end
c = random(pd); % triangular random variable between (0,1)
A = A ./ max(A(:)) * 9 * c; % range becomes (0, 9*c)
% diagonals are 1
for i=1:6
A(i,i) = 1;
end
% insert the result
M{m} = A;
end
There are actually 5 numbers are independent in 6x6 transitive matrix. The others are derived from them as shown in the code.
The reason why triangular distribution is used for these numbers is because pdf of triangular distribution is f(x)=x, and pdf of inverse triangular distribution is f-1(x)=1/x; thus their multiplication becomes uniform distribution. (See pdf of inverse distribution)
A = A ./ max(A(:)) * 9; makes the range (0,9), but there will always be 9 as the maximum element. We need to shrink the result by a random coefficient to obtain the result uniformly distributed in (0,9). Since A is uniformly distributed, we can achieve this again by triangular distribution. (See product distribution)
Another solution to the range issue would be calculating A while its maximum is above 9. This would eliminate the latter problem.
Since all elements of A depends on 5 random variables, the distribution of them will never be perfectly uniform, but the aim here is to maintain a reasonable scale for them.
It took me a litte to think about your question, but I realized there is no solution.
You require your elements of A to be uniformly distributed in the (0,9) range. You also require a_{ij}*a_{jk}=a_{ik}. Since the product of two uniform distributions is not a unifrom distribution, there is no solution to your question.

Approximating Poisson's equation using the finite element method with rectangular elements in MATLAB

I found an example using triangular elements here. I then went on to modify the way it generates the mesh to replace the triangular elements with rectangular ones, but I don't know how to integrate over them. Here is my version of it:
%3.6 femcode.m
% [p,t,b] = squaregrid(m,n) % create grid of N=mn nodes to be listed in p
% generate mesh of T=2(m-1)(n-1) right triangles in unit square
m=6; n=5; % includes boundary nodes, mesh spacing 1/(m-1) and 1/(n-1)
[x,y]=ndgrid((0:m-1)/(m-1),(0:n-1)/(n-1)); % matlab forms x and y lists
p=[x(:),y(:)]; % N by 2 matrix listing x,y coordinates of all N=mn nodes
nelems=(m-1)*(n-1);
t=zeros(nelems,3);
for e=1:nelems
t(e) = e + floor(e/6);
t(e, 2) = e + floor(e/6) + 1;
t(e, 3) = e + floor(e/6) + 6;
t(e, 4) = e + floor(e/6) + 7;
end
% final t lists 4 node numbers of all rectangles in T by 4 matrix
b=[1:m,m+1:m:m*n,2*m:m:m*n,m*n-m+2:m*n-1]; % bottom, left, right, top
% b = numbers of all 2m+2n **boundary nodes** preparing for U(b)=0
% [K,F] = assemble(p,t) % K and F for any mesh of rectangles: linear phi's
N=size(p,1);T=nelems; % number of nodes, number of rectangles
% p lists x,y coordinates of N nodes, t lists rectangles by 4 node numbers
K=sparse(N,N); % zero matrix in sparse format: zeros(N) would be "dense"
F=zeros(N,1); % load vector F to hold integrals of phi's times load f(x,y)
for e=1:T % integration over one rectangular element at a time
nodes=t(e,:); % row of t = node numbers of the 3 corners of triangle e
Pe=[ones(4,1),p(nodes,:),p(nodes,1).*p(nodes,2)]; % 4 by 4 matrix with rows=[1 x y xy]
Area=abs(det(Pe)); % area of triangle e = half of parallelogram area
C=inv(Pe); % columns of C are coeffs in a+bx+cy to give phi=1,0,0 at nodes
% now compute 3 by 3 Ke and 3 by 1 Fe for element e
grad=C(2:3,:);Ke=Area*grad'*grad; % element matrix from slopes b,c in grad
Fe=Area/3; % integral of phi over triangle is volume of pyramid: f(x,y)=1
% multiply Fe by f at centroid for load f(x,y): one-point quadrature!
% centroid would be mean(p(nodes,:)) = average of 3 node coordinates
K(nodes,nodes)=K(nodes,nodes)+Ke; % add Ke to 9 entries of global K
F(nodes)=F(nodes)+Fe; % add Fe to 3 components of load vector F
end % all T element matrices and vectors now assembled into K and F
% [Kb,Fb] = dirichlet(K,F,b) % assembled K was singular! K*ones(N,1)=0
% Implement Dirichlet boundary conditions U(b)=0 at nodes in list b
K(b,:)=0; K(:,b)=0; F(b)=0; % put zeros in boundary rows/columns of K and F
K(b,b)=speye(length(b),length(b)); % put I into boundary submatrix of K
Kb=K; Fb=F; % Stiffness matrix Kb (sparse format) and load vector Fb
% Solving for the vector U will produce U(b)=0 at boundary nodes
U=Kb\Fb % The FEM approximation is U_1 phi_1 + ... + U_N phi_N
% Plot the FEM approximation U(x,y) with values U_1 to U_N at the nodes
% surf(p(:,1),p(:,2),0*p(:,1),U,'edgecolor','k','facecolor','interp');
% view(2),axis equal,colorbar
I started to edit the section of the code which used to integrate over triangular elements but I'm not sure how to proceed or if it even is done in a similar way for rectangular elements.
UPDATE
So I've tried to incorporate what Dohyun suggested with my limited understanding and here's what I've got now:
m=12; n=12; % includes boundary nodes, mesh spacing 1/(m-1) and 1/(n-1)
[x,y]=ndgrid((0:m-1)/(m-1),(0:n-1)/(n-1)); % matlab forms x and y lists
p=[x(:),y(:)]; % N by 2 matrix listing x,y coordinates of all N=mn nodes
nelems=(m-1)*(n-1);
t=zeros(nelems,4);
a=0;
for e=1:nelems
t(e) = e + a;
t(e, 2) = e + a + 1;
t(e, 3) = e + a + m + 1;
t(e, 4) = e + a + m;
a = floor(e/n);
end
% final t lists 4 node numbers of all rectangles in T by 4 matrix
b=[1:m,m+1:m:m*n,2*m:m:m*n,m*n-m+2:m*n-1]; % bottom, left, right, top
% b = numbers of all 2m+2n **boundary nodes** preparing for U(b)=0
N=size(p,1);T=nelems; % number of nodes, number of rectangles
% p lists x,y coordinates of N nodes, t lists rectangles by 4 node numbers
K=sparse(N,N); % zero matrix in sparse format: zeros(N) would be "dense"
F=zeros(N,1); % load vector F to hold integrals of phi's times load f(x,y)
for e=1:T % integration over one rectangular element at a time
nodes=t(e,:); % row of t = node numbers of the 3 corners of triangle e
Pe=[ones(4,1),p(nodes,:),p(nodes,1).*p(nodes,2)]; % 4 by 4 matrix with rows=[1 x y xy]
Area=abs(det(Pe(1:3,1:3))); % area of triangle e = half of parallelogram area
C=inv(Pe); % columns of C are coeffs in a+bx+cy to give phi=1,0,0 at nodes
% now compute 3 by 3 Ke and 3 by 1 Fe for element e
% grad=C(2:3,:);
% constantKe=Area*grad'*grad; % element matrix from slopes b,c in grad
for i=1:4
for j=1:4
syms x y
Kn = int(int( ...
C(i,2)*C(j,2)+ ...
(C(i,2)*C(j,4)+C(i,4)*C(j,2))*y + ...
C(i,4)*C(j,4)*y^2 + ...
C(i,3)*C(j,3) + ...
(C(i,4)*C(j,3)+C(i,3)*C(j,4))*x + ...
C(i,4)*C(j,4)*x^2 ...
, x, Pe(1, 2), Pe(2, 2)), y, Pe(1, 3), Pe(3, 3));
K(nodes(i),nodes(j)) = K(nodes(i),nodes(j)) + Kn;
end
end
Fe=Area / 3; % integral of phi over triangle is volume of pyramid: f(x,y)=1
% multiply Fe by f at centroid for load f(x,y): one-point quadrature!
% centroid would be mean(p(nodes,:)) = average of 3 node coordinates
% K(nodes,nodes)=K(nodes,nodes)+Ke; % add Ke to 9 entries of global K
F(nodes)=F(nodes)+Fe; % add Fe to 4 components of load vector F
end % all T element matrices and vectors now assembled into K and F
% [Kb,Fb] = dirichlet(K,F,b) % assembled K was singular! K*ones(N,1)=0
% Implement Dirichlet boundary conditions U(b)=0 at nodes in list b
K(b,:)=0; K(:,b)=0; F(b)=0; % put zeros in boundary rows/columns of K and F
K(b,b)=speye(length(b),length(b)); % put I into boundary submatrix of K
Kb=K; Fb=F; % Stiffness matrix Kb (sparse format) and load vector Fb
% Solving for the vector U will produce U(b)=0 at boundary nodes
U=Kb\Fb; % The FEM approximation is U_1 phi_1 + ... + U_N phi_N
U2=reshape(U',m,n);
% Plot the FEM approximation U(x,y) with values U_1 to U_N at the nodes
surf(U2)
I think I can use definite integrals instead of numerical ones, but the result doesn't match that of the original program.
Result of my program
Result of original program
For P1 triangular element case, gradient happens to be constant. Hence integration is simply area*grad'*grad.
However, for bilinear case, inner product of gradient is 2nd order polynomial. Hence you need to use numerical integration.
So, inside of simple multiplication, you need another loop which computes basis value at quadrature points.
Also, your formula for area is wrong. Search for the affine mapping.
I have repository on github which implements poisson equation from 1D to 3D with arbitrary order polynomial. If you are interested, come visit https://github.com/dohyun64/fem_dohyun

How would I make a checkered pattern using a for loop in MATLAB for a user inputted dimension?

Basically the problem I can't solve is how to adapt into a for loop so depending on whatever dimensions I am given it does it on its own. This is an example using 2x2 dimensions. So for example if was to do 3x3 how would I do it in a for loop?
N=4;
R=2;
theta=zeros(1,N);
for k=1:N
theta(k)=2*pi*(k-1)/N;
end
x1=(R*cos(theta+pi/4)/sqrt(2));
y1=(R*sin(theta+pi/4)/sqrt(2));
plot(x1,y1);
fill(x1,y1,'w');
x2=(R*cos(theta+pi/4)/sqrt(2))+R;
y2=(R*sin(theta+pi/4)/sqrt(2));
plot(x2,y2);
fill(x2,y2,'y');
x3=(R*cos(theta+pi/4)/sqrt(2));
y3=(R*sin(theta+pi/4)/sqrt(2))+R;
plot(x3,y3);
fill(x3,y3,'y');
x4=(R*cos(theta+pi/4)/sqrt(2))+R;
y4=(R*sin(theta+pi/4)/sqrt(2))+R;
plot(x4,y4);
fill(x4,y4,'w');
hold;
You could set up a grid of points using ndgrid (or meshgrid).
To create index for the checker pattern, one trick is to use invhilb.
Below I used constant x and y instead of the one you created from R*cos(theta+pi/4)/sqrt(2)
% User input
N = 4;
% Basic square index
x = [0 1 1 0];
y = [0 0 1 1];
% Create axes and set to 'hold'
axes('NextPlot','Add')
% Create grid
[X,Y] = ndgrid(0:N-1);
% Loop over grid
for idx = 1:numel(X)
fh(idx) = fill(X(idx) + x, Y(idx) + y, 'w');
end
% Color as a check board (but with yellow)
set(fh(invhilb(N) > 0),'FaceColor','y')

Subtracting a row vector from every Row in a matrix

I was trying out something in an assignment I had. I wanted to subtract a row vector from every row of matrix(and then do further computations on it).
I have a matrix "X" of dimensions m X n and another one centroid of dimension K x n. I tried two varients,
function idx = findClosestCentroids(X, centroids)
K = size(centroids, 1);
m=size(X,1);
n=size(X,2);
idx = zeros(size(X,1), 1);
% ====================== CODE ======================
% Instructions: Go over every example, find its closest centroid, and store
% the index inside idx at the appropriate location.
% Concretely, idx(i) should contain the index of the centroid
% closest to example i. Hence, it should be a value in the
% range 1..K
%This Doesnt Work
% for i=1:m
% temp=ones(size(centroids))*diag(X(i))-centroids;
% temp=temp.^2;
% [x,y]=min(sum(temp,2));
% idx(i)=y;
% endfor
%This works!
for i=1:m
mini=1e10;
minin=-1;
for j=1:K
temp=X(i,:)-centroids(j,:);
temp=temp.^2;
sumx=sum(temp);
if (sumx<mini)
mini=sumx;
minin=j;
endif
endfor
idx(i)=minin;
endfor
% =============================================================
end
The first one works while the second one doesn't even though acc. to what I tried, second is just the vectorized version of the first one. Please guide me through the vectorization.
If you are looking for a MATLAB implementation, think this might serve your vectorization needs -
%%// Spread out centroids to the third dimension so that the singleton
%%// second dimension thus created could be used with bsxfun for expansion in
%%// that dimension
centroids1 = permute(centroids,[3 2 1]);
%%// Perform the much-needed subtraction
t1 = bsxfun(#minus,X,centroids1)
%%// Perform element-wise squaring and then min-finding as required too
t2 = t1.^2
t3 = sum(t2,2)
%%// Since the expansion resulted in data in third dimension, min-finding
%%// must be along it
[mini_array,idx] = min(t3,[],3)
Also, allow me to suggest an edit in your loop code. If you are interested in storing the minimum values as well at the end of each outer loop iteration, you might as well store it with something like min_array(i) = mini, just like you did when storing the indices.
Less parallelized than the other answer but much more easier to read:
for i = 1:size(X,1)
% z = centroids .- X(i, :); // Only Octave compatible
z = bsxfun(#minus, centroids, X(i, :));
zy = sum(z.^2, 2);
[~, idx(i)] = min(zy);
end

Plot lines between points in a matrix in MATLAB

I have a matrix with n rows and 4 columns. The columns are x0, y0, and x1, y1 (so basically I have n pairs of point coordinates in 2D). I want to draw a line between corresponding point pairs (that is, only between x0, y0 and x1, y1 of one row).
Is it possible to do it without a loop? Because the following works but is very slow.
for i = 1:size(A.data, 1)
plot([A.data(i, 1), A.data(i, 3)], [A.data(i, 2), A.data(i, 4)], 'k-')
end
I came here looking for the same answer. I basically want a horizontal line for each x,y point, starting with that point's x-y value, and ending at the x value of the next xy pair, without a line joining that segment to that of the next xy pair. I can make the segments by adding new points between, with the old y and the new x, but I didn't know how to break up the line segments. But your wording (matrix) gave me an idea. What if you load your xy pairs to a pair of x, y vectors and - wait for it - separate your pairs with nan's in both the x and y vectors. I tried that with a very long sine wave, and it seems to work. A ton of disjoint line segments, that plot and zoom instantly. :) See if it solves your problem.
% LinePairsTest.m
% Test fast plot and zoom of a bunch of lines between disjoint pairs of points
% Solution: put pairs of x1,y1:x2,y2 into one x and one y vector, but with
% pairs separated by x and or y = nan. Nan is wonderful, because it leaves
% your vector intact, but it doesn't plot.
close all; clear all;
n = 10000; % lotsa points
n = floor(n/3); % make an even set of pairs
n = n * 3 - 1; % ends with a pair
x = 1:n; % we'll make a sine wave, interrupted to pairs of points.
% For other use, bring your pairs in to a pair of empty x and y vectors,
% padding between pairs with nan in x and y.
y = sin(x/3);
ix = find(0 == mod(x,3)); % index 3, 6, 9, etc. will get...
x(ix) = nan; % nan.
y(ix) = nan; % nan.
figure;
plot(x,y,'b'); % quick to plot, quick to zoom.
grid on;
This works for the data structure I have:
data = [
0, 0, 1, 0;...
1, 0, 1, 1;...
1, 1, 0, 1;...
0, 1, 0, 0 ...
];
figure(1);
hold off;
%slow way
for i = 1:size(data, 1)
plot([data(i, 1) data(i, 3)], [data(i, 2) data(i, 4)], 'r-');
hold on;
end
%fast way ("vectorized")
plot([data(:, 1)' data(:, 3)'], [data(:, 2)' data(:, 4)'], 'b-');
axis equal
This particular example draws a square.
The key is that MATLAB draws lines column-wise in the arguments. That is, if the arguments of plot have n columns, the line will have n-1 segments.
In a "connect-the-dots" scenario where all points in the vectors must be connected, this is irrelevant because MATLAB will transpose to get a column vector if it needs to. It becomes important in my application because I do not want to connect every point on the list - only pairs of points.
Try line for example
X=[1:10 ; 2*(1:10)];
Y=fliplr(X);
line(X,Y)