How to create symbolic matrix dynamically in MATLAB? - matlab

I need to create a symbolic matrix in MATLAB. It can be done statically as
syms a11 a12 a21 a22;
A = [a11 a12; a21 a22];
or using compact syntax as
A = sym('A%d', [2 2]);
However i don't see how any of these syntax's should allow dynamic initialization. I would like to initialize each matrix element individually using two loops. One shot at a possible syntax (it's NOT valid MATLAB syntax) could be
syms a x1;
P = sym(zeros(n,n));
for l = 1:n
for m = 1:n
kl = l; km = m;
P(l,m)(x1) = a*sin(kl*x1)*sin(km*x1);
end
end
where I used the (invalid) syntax P(l,m)(x1) to specify that each element in P is a function of x1. Hence P(2) would be an (n,n) matrix with elements P(l,m) = a*sin(kl*2)*sin(km*2). I know it's possible to construct the P by building the matrix string (A=[...]) on run time and evaluating using eval. Something like
syms a x1;
command = [];
for i = 1:n
for j = 1:n
kl = i; km = j;
command = [command ' + a*sin(' num2str(kl) '*x1)*sin(' num2str(km) '*x1)'];
if(j < n) command = [command ',']; end
end
if(i < n) command = [command ';']; end
end
eval(['P(x1) = [' command '];'])
However, using eval is bad practice, so I see this solution only as a last resort. Is there any correct way to achieve my goal?
NB: I have written the elements P(l,m) = a*sin(kl*x1)*sin(km*x1) to simplify the code. The actual expression is P(l,m) = sin(kl*x1)*sin(km*x1)*epsilon + kl*km*cos(kl*x1)*cos(km*x1).*b + km*cos(km*x1)*sin(kl*x1)-kl*cos(kl*x1)*sin(km*x1)/(kl^2-km^2).

If you're just trying to avoid the for loops, you can use meshgrid, which hides them from you:
syms a x1
n = 3;
x = meshgrid(1:n)*x1; % multiplying by the symbolic x1 makes x symbolic
P = a*sin(x).*sin(x.');
which returns
P =
[ a*sin(x1)^2, a*sin(2*x1)*sin(x1), a*sin(3*x1)*sin(x1)]
[ a*sin(2*x1)*sin(x1), a*sin(2*x1)^2, a*sin(2*x1)*sin(3*x1)]
[ a*sin(3*x1)*sin(x1), a*sin(2*x1)*sin(3*x1), a*sin(3*x1)^2]

Related

solve equation using MATLAB solve

I have the following equation that I want to solve using MATLAB:
X is the unknown variable. I am trying to solve it using MATLAB solve, but I find it hard to code the left part of the equation.
Is it possible to use solve? Are there any other options?
EDIT
Since A and B depends respectively on j and i I have tried to put them in vectors as follows:
A = [A(1) ... A(j) ... A(N)]
B = [B(1) ... B(i) ... B(N)]
I was trying to have something that looks like this:
eqn = sum(A ./ sum(B .* D)) == C;
solve(eqn);
but the whole difficulty is in this part:
because it depends on both i and j.
To write equation you can use this code:
syms x real
C = 1;
beta = 10;
alph = 0.5;
N = 10;
lenA = N;
lenB = N;
A = rand(1,N);
B = rand(1,N);
eq = 0;
for j=2:N
eqaux = 0;
for i=1:N
eqaux = eqaux+B(i)/((alph+beta*x)^(i+j+1));
end
eq = eq+A(j)/eqaux;
end
eq = simplify(eq==C);
If x must be a complex number, delete real of syms x real.
To solve the equation use this code:
sol = solve(eq,x);
sol = vpa(sol);
Of course yu must use your own values of C, alph, beta, A, B and N.

"Variable in a parfor cannot be classified" MATLAB

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

Matlab: how can I perform row operations without brute-force for loop?

I need to do function that works like this :
N1 = size(X,1);
N2 = size(Xtrain,1);
Dist = zeros(N1,N2);
for i=1:N1
for j=1:N2
Dist(i,j)=D-sum(X(i,:)==Xtrain(j,:));
end
end
(X and Xtrain are sparse logical matrixes)
It works fine and passes the tests, but I believe it's not very optimal and well-written solution.
How can I improve that function using some built Matlab functions? I'm absolutely new to Matlab, so I don't know if there really is an opportunity to make it better somehow.
You wanted to learn about vectorization, here some code to study comparing different implementations of this pair-wise distance.
First we build two binary matrices as input (where each row is an instance):
m = 5;
n = 4;
p = 3;
A = double(rand(m,p) > 0.5);
B = double(rand(n,p) > 0.5);
1. double-loop over each pair of instances
D0 = zeros(m,n);
for i=1:m
for j=1:n
D0(i,j) = sum(A(i,:) ~= B(j,:)) / p;
end
end
2. PDIST2
D1 = pdist2(A, B, 'hamming');
3. single-loop over each instance against all other instances
D2 = zeros(m,n);
for i=1:n
D2(:,i) = sum(bsxfun(#ne, A, B(i,:)), 2) ./ p;
end
4. vectorized with grid indexing, all against all
D3 = zeros(m,n);
[x,y] = ndgrid(1:m,1:n);
D3(:) = sum(A(x(:),:) ~= B(y(:),:), 2) ./ p;
5. vectorized in third dimension, all against all
D4 = sum(bsxfun(#ne, A, reshape(B.',[1 p n])), 2) ./ p;
D4 = permute(D4, [1 3 2]);
Finally we compare all methods are equal
assert(isequal(D0,D1,D2,D3,D4))

How to write a generalized code

I write a code for linear feedback shift register.My code is in below:
X=5712;
D1(1)=0;
D2(1)=0;
D3(1)=0;
D4(1)=0;
D5(1)=0;
D6(1)=1;
for i=1:X-1
D6(i+1)=D1(i);
D5(i+1)=xor(D1(i),D6(i));
D4(i+1)=D5(i);
D3(i+1)=D4(i);
D2(i+1)=D3(i);
D1(i+1)=D2(i);
end
In my code i can only use 6 shift register.I know for degree,n=2,3,4,6,7,15,22, the polynomial is x^n+x+1.As the polynomial is same for those degrees so i want to write a common code for all.
Matlab experts Please need your help.
Your problem is that you are making separate vectors for each register. Rather make a single matrix (i.e. D replaces all of your D1, D2, ..., Dn) so that you can loop:
X = 20;
n = 6;
D = zeros(X, n);
D(1,n) = 1;
for ii = 1:X-1
D(ii+1, 1:n-2) = D(ii, 2:n-1);
D(ii+1, n-1) = xor(D(ii,1), D(ii,n));
D(ii+1, n) = D(ii, 1);
end
E = D(:, end:-1:1)

How to call automatically symbolic variables in a loop in Matlab

Is there anyway to use a loop index to call symbolic variables in Matlab? For example, consider the following code whose goal is to store the symbolic expression "x1+x2+x3" in "y".
syms x1 x2 x3
y = 0;
for i = 1:3
y = y + xi;
end
The code does not work because on each iteration Matlab reads "y = y + xi" and returns the error "xi is undefined", instead of reading "y = y + x1", "y = y + x2" and "y = y + x3", is there anyway around this?
Thanks.
I'd suggest this, provided that you can create your numbered symbolic variable slightly differently:
x = sym('x',[1 3]); % or: syms x1 x2 x3; x = [x1 x2 x3];
y = x(1);
for i = 2:numel(x)
y = y+x(i);
end
Of course in this simple example, the entire for loop and everything else can be replaced with:
y = sum(sym('x',[1 3]));
See the documentation on sym for more details.
EDIT: Note that, as #pm89 points out, by allocating the 1-by-3 symbolic vector x, you of course won't have direct access to the symbolic variables x1,x2, and x3 in your workspace, but will have to index them as shown. This is similar to working with arrays or cells and has many of the same benefits as my second vectorized example illustrates.
If your Matlab does not support the matrix declaration of symbolics directly (as sym('x',[3 1])) you can write your own function for that:
function out = Matrix_Sym(name, size) %#ok<STOUT>
rows = size(1);
cols = size(2);
S = '';
for k1 = 1:rows
for k2 = 1:cols
if rows == 1
S = [S name int2str(k2) ' '];
elseif cols == 1
S = [S name int2str(k1) ' '];
else
S = [S name int2str(k1) int2str(k2) ' '];
end
end
end
eval(['syms ' S]);
eval (['out = reshape([' S '], [rows, cols]);']);
Then you could get the same result with:
x = Matrix_Sym('x', [3 1])
...