Matlab get symbols from matrix to assign value - matlab

I am creating a matrix of symbols and I declare a function using them:
x = syms('x', [1 2]);
f = x(1) + x(2)
So x and f are:
x = [x1 x2];
f = x1 + x2
Now I want to give values to x1 and x2 in a for loop and evaluate f. But when I use:
x(1) = value;
then x becomes:
x = [1 x2]
and x1 is lost, so I cannot evaluate f. How can I assign a value to x1, x2, ..., xn and then evaluate f?

You should use subs like the following:
subs(f,x1,value)
instead of replacing symbol of x1 with a value.
You can see the details of the function here.

Related

Particular vector operation without loops

Given a vector x1, x2, ..., xN, I need to create a vector of (x_i + x_j) for i = 1,...,N, j = i+1,...,N.
E.g., for x1, x2, x3, x4:
x1+x2, x1+x3, x1+x4, x2+x3, x2+x4, x3+x4
How to do it without loops to get good performance?
C = combnk(v,k) returns a matrix containing all possible combinations of the elements of vector v taken k at a time.
So if you call
combnk(x,2)
you get
x3 x4
x2 x4
x2 x3
x1 x4
x1 x3
x1 x2
In case you rely on the order, which is now inverted, use flipud, then call sum
sum(flipud(combnk(x,2)),2)

How to specifically fprintf an array on a file

Lets say for example we have this array:
x =
0.5920 0.4635
0.6451 0.2118
-0.1206 -0.6036
0.2417 0.4773
0.3029 0.5172
What code would I need to write in order to print in such a way that it looks like this:
coords
x1 0.5920 y1 0.4635
x2 0.6451 y2 0.2118
x3 -0.1206 y3 -0.6036
x4 0.2417 y4 0.4773
x5 0.3029 y5 0.5172
I've tried this:
x = gallery('uniformdata',[1,10],0);
y = gallery('uniformdata',[1,10],1);
[v,c] = voronoin([x(:) y(:)]); %returns an array V with vertices and a cell array C with a matrix for each cell of the diagram.
c
for k = 1 : numel(c)
c{k} = c{k}(c{k} ~= 1)
end
fileID = fopen('cords.txt' , 'w');
for i=1:10
coord = v(c{i},:);
fprintf(fileID,'shape %d:\nx \t y\n', i);
fprintf(fileID,'%.4f %.4f\n', coord(:,1), coord(:,2));
end
fclose(fileID);
but im getting an output like this:
shape 10:
x y
0.5920 0.6451 %notice how the .6451 is on the right side when it should be on the bottom
-0.1206 0.2417
0.3029 0.4635
0.2118 -0.6036
0.4773 0.5172
The fprintf function reads the input variables in a column first manner and sends each value to its appropriate place in the string. So, in your code what happens is that even when you specify two different vectors per %.4f in your code, Matlab ignores that ordering. It puts the first value of coord(:, 1) in the first %.4f and the second value of coord(:, 1) in the second %.4f. Then it breaks the line. Then it again picks up the third value from coord(:, 1) and puts it in the first %.4f and so on. It only picks values from coord(:, 2) when all values of the first vector are exhausted.
The simplest fix is to transpose the coord matrix and then input it to Matlab like this:
fprintf(fileID,'%.4f %.4f\n', coord.'); % .' tranposes the matrix
Edit:
To get the format as x1 0.5920 y1 0.4635, we can make use of the column first ordering that Matlab follows to access a variable
% First we make a new matrix that has each of the required elements for the desired format
% The index of x, the value of x, the index of y and the value of y
tempCoord = [1:size(coord, 1); coord(:, 1).'; 1:size(coord, 1); coord(:, 2).'];
% Now we change the string specification for fprintf
fprintf(fileID,'x%d %.4f y%d %.4f\n', tempCoord);
Why does this work?
If you look at tempCoord, you will see that each of its columns has the format needed for the string specifier, i.e., the index of x, the value of x, the index of y and the value of y
tempCoord =
1.000000000000000 2.000000000000000 3.000000000000000 4.000000000000000 5.000000000000000
0.592000000000000 0.645100000000000 -0.120600000000000 0.241700000000000 0.302900000000000
1.000000000000000 2.000000000000000 3.000000000000000 4.000000000000000 5.000000000000000
0.463500000000000 0.211800000000000 -0.603600000000000 0.477300000000000 0.517200000000000
Now each column becomes each row of the printed file and you get the following output:
x1 0.5920 y1 0.4635
x2 0.6451 y2 0.2118
x3 -0.1206 y3 -0.6036
x4 0.2417 y4 0.4773
x5 0.3029 y5 0.5172

Creating multiples variables for syms

I want to create many variables such as x1, x2, x3 to use beside syms so it will look something like this:
syms x1 x2 x3 x4 ... x50 x51....xn
n is the number of variables I need.
Is there any way to do that?
x = sym('x', [n 1]);
This will create n symbolic variables i.e. x1, x2, x3 ......, xn and you can access them using x(1), x(2), x(3)....., x(n) respectively
For example with n=4, you'll get these results:
>> x
x =
x1
x2
x3
x4
>> x(1)
ans =
x1
>> x(3)
ans =
x3

Matlab gradient and hessian computation for symbolic vector function

I am trying to use the Matlab "gradient" and "hessian" functions to calculate the derivative of a symbolic vector function with respect to a vector. Below is an example using the sigmoid function 1/(1+e^(-a)) where a is a feature vector multiplied by weights. The versions below all return an error. I am new to Matlab and would very much appreciate any advice. The solution may well be under my nose in the documentation, but I have not been able to solve the issue. Thank you in advance for your help!
%version 1
syms y w x
x = sym('x', [1 3]);
w = sym('w', [1 3]);
f = (y-1)*w.*x + log(1/(1+exp(-w.*x)));
gradient(f, w)
%version 2
syms y w1 w2 w3 x1 x2 x3 x w
x = [x1,x2,x3];
w = [w1,w2,w3];
f = (y-1)*w.*x + log(1/(1+exp(-w.*x)));
%version 3
syms y w1 w2 w3 x1 x2 x3
f = (y-1)*[w1,w2,w3].*[x1,x2,x3] + log(1/(1+exp(-[w1,w2,w3].*[x1,x2,x3])));
Thanks, Daniel - it turns out the problem was in not having used dot() to take the dot product of w and x. Both diff() and gradient() gave the same solution, shown below:
syms y
x = sym('x', [1 3]);
w = sym('w', [1 3]);
f = (y-1)*dot(w,x) + log(1/(1+exp(dot(-w,x))));
diff(f, w(1))
gradient(f, w(1))
%ans =
%x1*(y - 1) + (x1*exp(- x1*conj(w1) - x2*conj(w2) - x3*conj(w3)))/
(exp(-x1*conj(w1) - x2*conj(w2) - x3*conj(w3)) + 1)

Symbolic Expression Differentiation using Symbolic Vector

I am trying to differentiate the following symbolic expression using a created symbolic vector but I keep getting errors. That is, I would like df/dx1, df/dx2, and df/dx3. Here is what I have tried:
>> x = sym('x', [3 1])
x =
x1
x2
x3
>> symbolic = 0.5*transpose(x)*eye(1)*x + [1 1 1]*x
symbolic =
x1^2/2 + x1 + x2^2/2 + x2 + x3^2/2 + x3
>> diff(symbolic, x)
Error using mupadmex
Error in MuPAD command: Invalid argument. [contains]
Evaluating: (Dom::Matrix(Dom::ExpressionField()))::_mult1
Error in sym/diff (line 44)
R = mupadmex('symobj::diff', S.s, x.s, int2str(n));
>> diff(symbolic, x.x1)
Error using sym/subsref
Too many output arguments.
Any assistance would be greatly appreciated. Thanks!
You can try one of these two options:
% option 1
x = sym('x', [3 1]);
f = 0.5*transpose(x)*eye(1)*x + [1 1 1]*x;
for i=1:3
Df(1,i) = diff(f, x(i));
end
% I do not like this option because I do not know
% how to evaluate the expressions with numeric values
x(1) = 1;
eval(Df)
I prefer the 'option 2', because it is easier to evaluate expressions.
% option 2
syms x1 x2 x3 real; % 'real' fixes x1 x2 x3 as real numbers (not complex ones)
x = [x1 x2 x3]'; % '
f = 0.5*transpose(x)*eye(1)*x + [1 1 1]*x;
for i=1:3
eval(['Df(1,i) = diff(f,x',num2str(i),');']);
end
% To eval at a certain value
x1 = 1;
x2 = 2;
x3 = 3;
eval(Df)
I think that eval has only the two functions I used above:
To eval symbolic expressions to specific values of the symbolic variables, like when I wrote eval(Df).
You can use eval to evaluate a matlab command written as a string, as if you were writing it as normal code. Try this to see what I mean:
a = 1; % set value of a to 1
eval('a = 2'); % change value of a to 2
eval(['a = ',num2str(5)]); % set value of a to 5;
Hope this helps,