I've got a problem with a parfor loop: when I want to run a code whose structure is very similar to that of the code shown below, I obtain the
Subscripted assignment dimension mismatch error
I run the code with
dbstop if error
and I've observed that the indexes i and j are well iterated but the results aren't avalaible to my wokspace. Do you have any idea?
matlabpool 12;
Nx = 51;
Ny = 53;
Nc = 11;
Ns = randn(Ny,Nx);
Nr = randn(Nc, 2^14);
Ne = randn(1, Nc);
parfor j = 1:Ny
tic
for i = 1:Nx
idx = randi([1,Nc],1,19);
if isempty(idx)
continue
end
a = Nr(idx,:);
b = Ne(idx)';
nrr = sum(bsxfun(#(a, b) a.*b, a, b)/(Ns(j,i)),1);
nrrr(j,i,:) = nrr;
end
toc
end
PS: This code isn't the real one but I can assure you that the types of operations are kept as those in the real one (the real one is found inside a very large script).
Related
I am calculating sort of a histogram based on the distance between a pair of points in 3d space:
numBins = 20;
binWidth = 2.5;
pop = zeros(1,numBins);
parfor j=1:particles
r1 = coords(j,:);
for k=j+1:particles
r2 = coords(k,:);
d = norm(r1-r2);
ind = ceil(d/binWidth);
pop(ind) = pop(ind) + 1;
end
end
This, expectedly, results in
Error: The variable pop in a parfor cannot be classified.
I understand the problem, but I am confused as to how can I solve it.
In principle, what could be done is to have n copies of pop = zeroes(1,numBins) be sent to each of n workers, and joined by adding each copy together at the end of computation. How can I do this here? Or is there another, more standard way of solving the problem?
There is two things that don't work in your code:
1) for k = j+1:particles
In a parfor a nested loop should have fixed bound.
2) pop(ind)
Matlab is afraid that the for-loop order matters and display an error message. Even if, in your specific case, the order doesn't matters (But matlab is not smart enough to know that).
The solution, Linearization:
%Dummy data
numBins = 20;
binWidth = 2.5;
particles = 10;
coords = rand(10,2)*40;
%Initialization
pop = zeros(1,numBins);
parfor j=1:particles
r1 = coords(j,:)
r2 = coords((j+1):end,:)
d = sqrt(sum([r1-r2].^2,2)) % compute each norm at the same time !
pop = pop + histcounts(ceil(d/binWidth),0:numBins)
end
You can create a function that computes the inner loop and use a handle to it in the parfor (I didn't tested it but I think it should work according to the documentation):
function pop = hist_comp(pop,j,particles,coords,binWidth)
r1 = coords(j,:);
for k=j+1:particles
r2 = coords(k,:);
d = norm(r1-r2);
ind = ceil(d/binWidth);
pop(ind) = pop(ind) + 1;
end
end
numBins = 20;
binWidth = 2.5;
particles = 10;
coords = rand(10,2)*5;
pop = zeros(1,numBins);
f = #(pop,j) hist_comp(pop,j,particles,coords,binWidth);
parfor j=1:particles
pop = f(pop,j);
end
I am trying to convert my code over to run with parfor, since as it is it takes a long time to run on its own. However I keep getting this error. I have search around on the website and have read people with similar problems, but none of those answers seem to fix my problem. This is my code:
r = 5;
Mu = 12.57e-9;
Nu = 12e6;
I = 1.8;
const = pi*Nu*Mu*r*I;
a = 55;
b = 69;
c = 206;
[m,n,p] = size(Lesion_Visible);
A = zeros(m,n,p);
parpool(2)
syms k
parfor J = 1:m
for I = 1:n
for K = 1:p
if Lesion_Visible(J,I,K) ~= 0
Theta = atand((J-b)/(I-a));
Rho = abs((I-a)/cosd(Theta))*0.05;
Z = abs(c-K)*0.05;
E = vpa(const*int(abs(besselj(0,Rho*k)*exp(-Z*k)*besselj(0,r*k)),0,20),5);
A (J,I,K) = E;
end
end
end
end
I'm trying to calculate the electric field in specific position on an array and matlab give me the error "The variable A in a parfor cannot be classified". I need help. Thanks.
As classification of variables in parfor loop is not permitted, you should try to save the output of each loop in a variable & then save the final output into the desired variable, A in your case!
This should do the job-
parfor J = 1:m
B=zeros(n,p); %create a padding matrix of two dimension
for I = 1:n
C=zeros(p); %create a padding matrix of one dimension
for K = 1:p
if Lesion_Visible(J,I,K) ~= 0
Theta = atand((J-b)./(I-a));
Rho = abs((I-a)./cosd(Theta))*0.05;
Z = abs(c-K).*0.05;
E = vpa(const.*int(abs(besselj(0,Rho.*k).*exp(-Z.*k).*besselj(0,r.*k)),0,20),5);
C(K) = E; %save output of innnermost loop to the padded matrix C
end
end
B(I,:)=C; % save the output to dim1 I of matrix B
end
A(J,:,:)=B; save the output to dim1 J of final matrix A
end
Go through the following for better understanding-
http://www.mathworks.com/help/distcomp/classification-of-variables-in-parfor-loops.html
http://in.mathworks.com/help/distcomp/sliced-variable.html
I had written the following matlab code to optimize the following LP
max b'x
s.t A'x <= 0;
x <= d;
Also d is
d = {1,2..m}
and A is defined in the code. I am getting the error:
Maximum number of iterations exceeded; increase options.MaxIter.
Upon googling, someone said it is not very good that the error is occuring. and the problem has to reformulated. Any idea how to reformulate it.
The solution is very simple as A > 0, b> 0 and d>0 therefore x = 0
m = 10;
d = [1:1:m];
for j = 1:m,
for i = 1:m,
A(i,j) = 1/(i+j-1);
end
end
for i = 1:m,
b(i)=0;
end
for i = 1:m
lb(i) = -inf;
end
b;
lb = lb';
f = A*d';
[x,fval,exitflag,output] = linprog(-f,A,b,[],[],lb,d); %minimzation problem. Hence -f, A = A'
I'd used the optimist = ('MaxIter', 10000). To stop that error message.
So, I'm trying to do the Gauss-Seidel method in Matlab and I found a code that does this but when I apply it to my matrices I get the Subscripted assignment dimension mismatch. error. I will show you my code in order to get a better idea.
%size of the matrix
n = 10;
%my matrices are empty in the beginning because my professor wants to run the algorithm for n = 100
and n = 1000. A's diagonal values are 3 and every other value is -1. b has the constants and the
first and last value will be 2,while every other value will be 1.
A = [];
b = [];
%assign the values to my matrices
for i=1:n
for j=1:n
if i == j
A(i,j) = 3;
else
A(i,j) = -1;
end
end
end
for i=2:n-1
b(i) = 1;
end
%here is the Gauss-Seidel algorithm
idx = 0;
while max(error) > 0.5 * 10^(-4)
idx = idx + 1;
Z = X;
for i = 1:n
j = 1:n; % define an array of the coefficients' elements
j(i) = []; % eliminate the unknow's coefficient from the remaining coefficients
Xtemp = X; % copy the unknows to a new variable
Xtemp(i) = []; % eliminate the unknown under question from the set of values
X(i) = (b(i) - sum(A(i,j) * Xtemp)) / A(i,i);
end
Xsolution(:,idx) = X;
error = abs(X - Z);
end
GaussSeidelTable = [1:idx;Xsolution]'
MaTrIx = [A X b]
I get the error for the Xsolution(:,idx) = X; part. I don't know what else to do. The code posted online works though, and the only difference is that the matrices are hardcoded in the m-file and A is a 5x5 matrix while b is a 5x1 matrix.
I am unable to run your code because some variables are not initialised, at least error and X. I assume the Problem is caused because Xsolution is already initialised from a previous run with a different size. Insert a Xsolution=[] to fix this.
Besides removing the error I have some suggestions to improve your code:
Use Functions, there are no "left over" variables from a previous run, causing errors like you got here.
Don't use the variable name error or i. error is a build-in function to throw errors and i is the imaginary unit. Both can cause hard to debug errors.
Initialise A with A=-1*ones(n,n);A(eye(size(A))==1)=3;, it's faster not to use a for loop in this case. To initialise b you can simply write b(1)=0;b(2:n-1)=1;
Use preallocation
the first time you run the code, Xsolution(:,idx) = X will create a Xsolution with the size of X.
the second time you run it, the existing Xsolution does not fit the size of new X.
this is another reason why you always want to allocate the array before using it.
One of the tasks for my assignment is to add an appropriate noise function to the following equation:
x = A*(1+a1*E)*sin(w*(1+a2*E)*t+y)+ a3*E
We must then plot the noise function vs. time as well as the original function with the noise added. I have asked the professor if a random number generator between -1 and 1 will suffice and he has agreed. I have the following code so far:
t = 0:0.1:6.5;
A = 2;
a1 = 2;
a2 = 4;
a3 = 3;
w = 1;
y = 2;
for i=1:length(t)
E(i) = random('unif', -1, 1, 1, 1);
x(i) = A*(1+a1*E(i))*sin(w*(1+a2*E(i))*t+y)+ a3*E(i);
i=i+1;
end
plot(t,E)
figure
stem(t,x)
I keep getting the following error In an assignment A(I) = B, the number of elements in B and I must
be the same.
Error in Try1 (line 58)
x(i) = A*(1+a1*E(i))*sin(w*(1+a2*E(i))*t+y)+ a3*E(i);
I don't understand the error because the E is just one number.
Any help appreciated!! Thanks!!
You're correct that E is just one number, but you're multiplying by t, which is not just one number - it's an array. I think you meant to multiply by t(i).
here------v
x(i) = A*(1+a1*E(i))*sin(w*(1+a2*E(i))*t(i)+y)+ a3*E(i);