im getting a vertcat error in my for loop, i have looked about for a solution but i cant seem to find one that has a matrix in the loop. It also appears to solve the loop once then get stuck the second time round. this is my code:
the error is at matrix A, any help would be greatly appreciated, thanks.
phi=1:1:89;
for i=1:length(phi)
m=cosd(phi(1:i));
l=sind(phi(1:i));
%the following calculates k tilde ratio for use in solving of equations
r= U1/U2; %velocity ratio
Kratio = ((r*(mach2/(1-mach2^2)))*(-m*mach2 + l*sqrt((m.^2/l.^2)-(((1/r)^2)*
((1/mach2^2)-1)))));
alpha = (A2^2/(gamma*U1^2))*(Kratio/(m-(Kratio*(1/r))));
beta= (A2^2/(gamma*U1^2))*(l/(m-(Kratio*(1/r))));
%from boundary conditions
B1= (((gamma-1)*(mach1^2))-2)/((gamma+1)*(mach1^2));
B2= 2/((gamma+1)*mach1^2);
C1=4/(((gamma-1)*mach1^2)+2);
C2= -(((gamma-1)*mach1^2)+4)/(((gamma-1)*mach1^2)+2);
D1= (4*gamma*mach1^2)/((2*gamma*mach1^2)-(gamma-1));
D2=-((2*gamma*mach1^2)/((2*gamma*mach1^2)-(gamma-1)));
E1= (2*(mach1^2-1))/((gamma+1)*mach1^2);
%matrix to be solved for unknown coefficients
matrixA= [1 0 0 -alpha 0 0 0; 0 ((m*r)) 0 0 l 0 0; 0 0 1 -beta 0 0 0; 1 1 0 0 0
(B1-1) 0; 0 0 0 1/gamma 0 C1 1; 0 0 0 1 0 D1 0; 0 0 1 0 1 ((E1*l)/m) 0];-->error here
matrixB= [0 ; 0 ; 0 ; -B2*Ae+B1*l*Av ; C1*l*Av-C2*Ae ; D1*l*Av-D2*Ae; -m*Av];
format long
coefficients= matrixA\matrixB;
i=sqrt(-1);
t=0;
F=coefficients(1,1);
G=coefficients(2,1);
H=coefficients(3,1);
K=coefficients(4,1);
I=coefficients(5,1);
L=coefficients(6,1);
Q=coefficients(7,1);
% assumes k=1 for equation Kratio,t=0 for this case (test)
%N=201;
%x=zeros(N);
%for j=1:N
x=20;
x1=-20;
%end
%for j=1:N
y=0;
y2=0;
%upstream and downstream conditions
%plots the graph for fixed t
% k has been set to 2
%entropy modes
%vorticity modes
%plot for upstream KE
u1prime= l*Av*exp(k*i*(m*x1+l*y2-U1*m*t));
v1prime= -m*Av*exp(k*i*(m*x1+l*y2-U1*m*t));
KE1= u1prime.*conj(u1prime)+v1prime.*conj(v1prime);
%plot for downstream KE (kinetic engery)
u2prime2=F*exp(k*i*Kratio*x+k*i*l*y-k*i*U1*m*t)+G*exp((k*i*(m*r*x+l*y-U1*m*t)));
v2prime2=H*exp(k*i*Kratio*x+k*i*l*y-k*i*U1*m*t)+I*exp((k*i*(m*r*x+l*y-U1*m*t)));
KE=u2prime2.*conj(u2prime2)+v2prime2.*conj(v2prime2);
KEnorm=(KE)/KE1
end
Your problem arises from (m*r) (and another one will arise with l in matrixB).
m and l grow inside the loop:
m=cosd(phi(1:i));
l=sind(phi(1:i));
It's up to you to figure out which portion of m and l you want to use after the first iteration.
As Dan pointed out, the route to debug this is to set a breakpoint in the line that gives the error. Once you get to it, check all the variables in your matrix for their size.
One last comment: I had to assume the following variables:
U1 = 1.0;
U2 = 0.5;
mach2 = 0.3;
mach1 = 0.5;
A2 = 0.6;
gamma = 1.4;
Ae = 1;
Av = 1;
k = 1;
Next time, please consider providing a minimal working example, that upon copy/paste will regenerate your problem.
EDIT
If you attempt to fix your code, consider the following steps:
As Divakar suggested, do not use i as the loop counter, when you need it as the imaginary unit. Therefore, replace all instances of the loop counter with ii (take your time doing this, you do not want to overlook one instance).
Next, you have two choices:
either, replace m and l with this:
m=cosd(phi(ii));
l=sind(phi(ii));
that way, both m and l will remain scalars
or, replace every instance of m and l with m(ii) and l(ii) respectively
whichever you do, be consistent.
Related
To better explain what I need, here is my first code:
function allpos = f1(x)
allpos=reshape(permute((dec2base(0:power(2,x*x)-1,2)-'0'),[3 2 1]),x,x,[]);
This code does exactly what I need it to. If the users inputs f1(2), it returns every matrix from [0 0; 0 0] to [1 1; 1 1]. However, it also gives me a lot of useless matrices. I only want matrices that are mirrored across the diagonal, with only zeros on the diagonal.
To put more simply, for f1(3), I only want
[0 0 0; 0 0 0; 0 0 0] to [0 1 1; 1 0 1; 1 1 0]. That means that if I run the new f1(3); it will return 8 matrices, not 512.
How do I rewrite the function to do this? I know that it will require some sort of addition of a triangular matrix and its transposed self, but I cant piece it together. Thanks!
It can probably be made more concise but the following does what you ask.
function allpos = f1(x)
N = (x-1)*x / 2;
z = permute(dec2base(0:power(2,N)-1,2)-'0',[3 2 1]);
allpos = zeros(x,x,power(2,N));
idx = repmat(logical(tril(ones(x),-1)),[1,1,power(2,N)]);
allpos(idx) = z(:);
allpos = permute(allpos,[2 1 3]);
allpos(idx) = z(:);
A similar solution to #jodag's one, but more concise...
function allops=f1(x)
allops=zeros(x,x,2^(sum(1:x-1)));
allops(find(triu(ones(x),1))+x^2*(0:2^(sum(1:x-1))-1))=[dec2base(0:2^(sum(1:x-1))-1,2)-'0'].';
allops=allops+permute(allops,[2 1 3])
end
I have an mxn array r in Matlab with elements that are zeros or ones.
I want to construct a vector p of dimension mxn such that for i=1,...,m
p(i,1)=r(i,1)
p(i,2)=r(i,2)XOR r(i,1)
p(i,3)=r(i,3) XOR r(i,2)
...
p(i,n)=r(i,n) XOR r(i,n-1)
This code does what I want but it is slow for m,n large. Could you suggest something faster?
m=4;
n=5;
r=[1 1 1 1 1; ...
0 0 1 0 0; ...
1 0 1 0 1; ...
0 1 0 0 0];
p=zeros(m,n);
for i=1:m
p(i,1)=r(i,1);
for j=2:n
p(i,j)=xor(r(i,j),r(i,j-1));
end
end
Sure:
p = zeros(m,n);
p(:,1) = r(:,1);
p(:,2:end) = xor( r(:,1:(end-1)), r(:,2:n) );
What we're doing here is:
Pre-allocating the array. Same as your code.
Fill in the first column of p with the first column of r
Fill in the 2nd - last columns of p with the desired XOR operation. As inputs to the XOR we are using two large sections of r. The first is the 1st - (last-1)th columns. The second is the 2nd through last columns.
I have a matrix (89x42) of 0's and 1's that I'd like to multiply combinations of rows together.
For example, for matrix
input = [1 0 1
0 0 0
1 1 0];
and with 2 combinations, I want an output of
output = [0 0 0; % (row1*row2)
1 0 0; % (row1*row3)
0 0 0] % (row2*row3)
Which rows to multiply is dictated by "n Choose 2" (nCk), or all possible combinations of the rows n taken k at a time. In this case k=2.
Currently I am using a loop and it works fine for the 89C2 combinations of rows, but when I run it with 89C3 it takes far too long too run.
What would be the most efficient way to do this program so I can do more than 2 combinations?
You can do it using nchoosek and element-wise multiplication.
inp = [1 0 1; 0 0 0; 1 1 0]; %Input matrix
C = nchoosek(1:size(inp,1),2); %Number of rows taken 2 at a time
out = inp(C(:,1),:) .* inp(C(:,2),:); %Multiplying those rows to get the desired output
Several things you can do:
Use logical ("binary") arrays (or even sparse logical arrays) instead of double arrays.
Use optimized combinatorical functions.
bitand or and instead of times (where applicable).
Vectorize:
function out = q44417404(I,k)
if nargin == 0
rng(44417404);
I = randi(2,89,42)-1 == 1;
k = 3;
end
out = permute(prod(reshape(I(nchoosek(1:size(I,1),k).',:).',size(I,2),k,[]),2),[3,1,2]);
I'm unsure how to phrase the question, but I think an example will help. Suppose I have a vector y = [3;1;4;1;6]. I want to create the matrix Y =
[0 0 1 0 0 0;
1 0 0 0 0 0;
0 0 0 1 0 0;
1 0 0 0 0 0;
0 0 0 0 0 1]
↑ ↑ ↑ ↑ ↑ ↑
1 2 3 4 5 6
where the element on each column is one or zero corresponding to the value in the vector.
I found that I could do it using
Y = []; for k = 1:max(y); Y = [Y (y==k)]; end
Can I do it without a for loop (and is this method more efficient if y has thousands of elements)?
Thanks!
Your method is not efficient because you're growing the size of Y in the loop which is not a good programming practice. Here is how your code can be fixed:
Ele = numel(y);
Y= zeros(Ele, max(y));
for k = 1:Ele
Y (k,y(k))= 1;
end
And here is an alternative approach without a loop:
Ele = numel(y); %Finding no. of elements in y
Y= zeros(Ele, max(y)); % Initiailizing the matrix of the required size with all zeros
lin_idx = sub2ind(size(Y), 1:Ele, y.'); % Finding linear indexes
Y(lin_idx)=1 % Storing 1 in those indexes
You can use bsxfun:
result = double(bsxfun(#eq, y(:), 1:max(y)));
If you are running the code on Matlab version R2016b or later, you can simplify the syntax to
result = double(y(:)==(1:max(y)));
Another approach, possibly more efficient, is to fill in the values directly using accumarray:
result = accumarray([(1:numel(y)).' y(:)], 1);
I found another solution:
E = eye(max(y));
Y = E(y,:);
Another solution:
Y = repmat(1:max(y), size(y)) == repmat(y, 1, max(y))
I have two Matrices: Matrix 1: A, that is the Matrix I have in the beginning and Matrix 2: B that has some values from A permuted. Both are filled with only ones and zeros (mainly zeros)
for example
0 0 0 0 0 1
A = 0 1 0 and B = 0 0 0
0 0 0 0 0 0
where I move the value 1 from the middle of matrix A to the top right corner in matrix B. I can do this manually by multiplicating with the Transformation-matrices T1 and T2.
for the example above:
0 1 0 0 0 0
T1 = 0 0 0 and T2 = 0 0 1 such that P1 * A * P2 = B
0 0 0 0 0 0
How can I calculate these two Transformation-matrices P1 and P2 with Matlab really fast (for matrices > 5000x5000) by only knowing matrix A and B?
The goal is to move some of the ones with every step on matrix A. As I have some other Matrices that act like layers, I would like to move them the same way, so I'd like to get T1 and T2 so I can change them the same way.
So the problem is that I have an island, that I get from GoogleMaps, that I convert in 0 (water) and 1 (land) and I randomly put People on that Map M. Then I randomly set the position of some people where M has a one. These people are set on matrix A with a one, rest is zero. The people move, the new position is given by Matrix B. While not all people are infected by zombies yet, I have a vector, that defines a subMatrix, where the zombies are. This little Matrix is the important one, so I move my zombie and some other attributes, that the zombie has (they are defined by other Matrices, I call them lazer Matrices). So I only want the changes of the Zombiematrix tracked (for that I need the Transformation Matrix), so that all layer matrices that have the attributes of the zombie Submatrix are moved the same way. The ZombieMatrix then grows bigger and bigger, the more people are infected. To save time, I look for a subMatrix that contains all the Zombies by each step and then perform the Transformationmatrix on this subMatrix.
I know that sounds all fuzzy, that's why I just asked the way above the line.
Since your problem is nonlinear it can have multiple solutions, from which the comment of #knedlsepp. For this reason I think that resorting to a genetic algorithm might be a good option, naturally without looking at the performances...
Let us reformulate your problem as an optimization one
Here we will adopt the Frobenius norm.
Then the code would look like
%// Build the test matrices
A = [0 0 0 ; 0 1 0 ; 0 0 0];
B = [0 0 1 ; 0 0 0 ; 0 0 0];
n = size(A, 1);
%// Define the optimization problem.
nvars = 2*n^2;
lb = zeros(nvars, 1);
ub = ones(nvars, 1);
intCon = 1:nvars;
options = gaoptimset();
%// Solve the problem.
[t,err,exitflag] = ga(#(t) fitnessfcn(t, A, B, n), ...
nvars, [], [], [], [], lb, ub, [], intCon, options);
%// Retrieve the solution
T1 = reshape(t(1:n^2), n, n);
T2 = reshape(t(n^2+1:end), n, n);
and fitnessfcn is
function err = fitnessfcn(t, A, B, n)
T1 = reshape(t(1:n^2), n, n);
T2 = reshape(t(n^2+1:end), n, n);
E = T1*A*T2-B;
err = norm(E, 'fro');
I hope that by playing with the options you can apply this code to more realistic cases.