Matlab symbolic function susbstitution - matlab

I am defining a symbolic function
syms x(n);
x(n) = (n==0);
n=-1:1;
When I try x(n)+x(n-1)
I get
[ -1 == 0, 0 == 0, 1 == 0]
+[ -2 == 0, -1 == 0, 0 == 0]
=[ -3 == 0, -1 == 0, 1 == 0]
I want to force the symbolic function to substitute the values so I get the following results instead.
[ 0, 1, 0]
+[ 0, 0, 1]
=[ 0, 1, 1]
I tried something like x(n) = logical(n==0); and x(n) = double(n==0); but I got the same result.
I know that double(x(n))+double(x(n-1)) works, but I want to use x(n) directly and do the substitution in the definition of the symbolic function.
Can this be done?

I think piecewise is the only way to cast a boolean to an integer in Mupad. Unfortunately, it only available in Mupad itself, so you have to use evalin to get it:
syms asinteger(fun) x(n)
asinteger(fun) = evalin(symengine,'piecewise([fun,1],[Otherwise,0])');
x(n) = asinteger(n==0);
n=-1:1;
>> x(n)+x(n-1)
ans =
[ 0, 1, 1]
Think of the asinteger function as the symbolic version of double or int64.

I think the easiest way to do is to use isAlways, which evaluates if an expression (equality or inequality) is true:
syms x(n);
x(n) = (n==0);
m = -1:1; % Use a different variable to not overwrite symbolic n
isAlways(x(m))+isAlways(x(m-1))
Or you can use an anonymous function to avoid multiple calls to isAlways:
m = -1:1;
x = #(n)isAlways(sym(n)==0);
x(m)+x(m-1)
Both of these return an array of doubles ([0 1 1]). You can use logical to convert this to a logical array. You might also find sym/isequaln useful in some cases.

Related

Why in the content of cvx, subs() does not work?

TLDR
I wrote a code to solve a SDP problem. I used subs to change syms into numerical value before cvx content and I did see the numerical value after I printed out the variables. But whos() did show that the variable is still syms type which I think might be the key point where I went wrong. The error message shows like this:
Unable to convert 'cvx' to 'sym'.
It went wrong at the line trace(rhot*X_ele(:,:,i)) == value(i); where rhot is symbolic instead of numeric.
Details
I'm trying to write a SDP problem as follows:
function [res] = NH_SDP(rhot,p,value,t)
dim = size(rhot,1);
for i = 1:p
drhot(:,:,i) = diff(rhot,t(i));
end
drhot = subs(drhot,t,value);
rhot = subs(rhot,t,value);
rhott = kron(eye(p),rhot);
% cvx process
cvx_begin sdp
% cvx part
variable L_ele(dim,dim,(1+p)*p/2) hermitian;
variable X_ele(dim,dim,p) hermitian;
cnt = 1;
for i = 1:p
for j = i:p
if i == j
L((i-1)*dim+1:i*dim,(j-1)*dim+1:j*dim) = L_ele(:,:,cnt);
cnt = cnt + 1;
else
L((i-1)*dim+1:i*dim,(j-1)*dim+1:j*dim) = L_ele(:,:,cnt);
L((j-1)*dim+1:j*dim,(i-1)*dim+1:i*dim) = L_ele(:,:,cnt);
cnt = cnt + 1;
end
end
end
for i = 1:p
X((i-1)*dim+1:i*dim,1:dim) = X_ele(:,:,i);
end
for i = 1:p
X2(1:dim,(i-1)*dim+1:i*dim) = X_ele(:,:,i);
end
% rhott = [[0, 0, 0, 0, 0, 0, 0, 0]
% [0, 1/2, 7/20, 0, 0, 0, 0, 0]
% [0, 7/20, 1/2, 0, 0, 0, 0, 0]
% [0, 0, 0, 0, 0, 0, 0, 0]
% [0, 0, 0, 0, 0, 0, 0, 0]
% [0, 0, 0, 0, 0, 1/2, 7/20, 0]
% [0, 0, 0, 0, 0, 7/20, 1/2, 0]
% [0, 0, 0, 0, 0, 0, 0, 0]];
rhott = double(rhott);
rhot = double(rhot);
drhot = double(drhot);
minimize(trace(rhott*L));
subject to
% rhot = [0 0 0 0;0 1/2 7/20 0;0 7/20 1/2 0;0 0 0 0];
% drhot
for i =1:p
trace(rhot*X_ele(:,:,i)) == value(i);
end
for i = 1:p
for j = 1:p
if i == j
trace(drhot(:,:,i)*X_ele(:,:,j)) == 1;
else
trace(drhot(:,:,i)*X_ele(:,:,j)) == 0;
end
end
end
% semidefinit constraint.
[L X; X2 eye(dim)] >= 0;
cvx_end
res = cvx_optval;
X_ele
end
There are three line in the above code:
rhott = double(rhott);
rhot = double(rhot);
drhot = double(drhot);
If I delete those three lines, there will be error Unable to convert 'cvx' to 'sym'. while my rhot have already changed into numerical value by subs function and I print it out to see numerical numbers even though whos function show that the type of rhot is still syms.
To cite the documentation on subs():
snew = subs(s,old,new) returns a copy of s, replacing all occurrences
of old with new, and then evaluates s. Here, s is an expression of
symbolic scalar variables or a symbolic function, and old specifies
the symbolic scalar variables or symbolic function to be substituted.
emphasis mine. In other words: subs() changes your symbolic expression to a new symbolic expression.
double() on the other hand, converts whatever you feed it to a type double, i.e. a numeric value. rhott thus initially contains a symbolic value, even if that is a number. double(rhott) then evaluates it to a numeric number, rather than a symbolic one.
I presume the problem is here
drhot = subs(drhot,t,value);
rhot = subs(rhot,t,value);
rhott = kron(eye(p),rhot);
You're substituting all occurrences of t within drhot with value, and then again on rhot. if drhot is already symbolic, i.e. if the inputs rhot, value, t are symbolic, this makes sense and indeed a double call will make your system numeric, rather than symbolic. If, on the other hand, all inputs are numeric, subs() unnecessarily converts everything to symbolic variables, slowing execution speed.

How to create an Octave function for evaluating sum of odd numbers in the vector only?

I created a function file on Octave like this,
function y = sum_odd(n)
if rem(n,2) ==1
sum_odd = sum(n)
endif
endfunction
and I want to make the function evaluate the sum of odd numbers in every vectors.
But when I tried sum_odd([1 2 3]), it didn't calculate for me.
Any ideas how to fix this problem?
You can simply use logical indexing:
function y = sum_odd(n)
y = sum(n(rem(n,2)==1))
end
rem([1 2 3],2)==1) returns logical array: [1 0 1].
n(logical([1 0 1])) returns[1 3]`.
sum(n(rem([1 2 3], 2) == 1)) returns sum of [1 3].

Operations on adjacent elements in a vector

I have a binary vector, if I find a 0 in the vector I want to make the adjacent elements 0 if they are not already.
For example if input = [1 1 0 1 1] I want to get output = [1 0 0 0 1]
I tried the following but it's messy and surely there is a neater way:
output=input;
for i = 1:length(input)
if(input(i) == 0)
output(i-1)=0;
output(i+1)=0;
end
end
In = [1, 1, 0, 1, 1]; % note that input is a MATLAB function already and thus a bad choice for a variable name
Find the zeros:
ind_zeros = ~In; % or In == 0 if you want to be more explicit
now find the indicies before and after
ind_zeros_dilated = ind_zeros | [ind_zeros(2:end), false] | [false, ind_zeros(1:end-1)]
Finally set the neighbours to zero:
Out = In;
Out(ind_zeros_dilated) = 0
For fun, an alternative way to calculate ind_zeros_dilated is to use convolution:
ind_zeros_dilated = conv(ind_zeros*1, [1,1,1],'same') > 0 %// the `*1` is just a lazy way to cast the logical vector ind_zeros to be of type float

How to find the linear parameterization of a symbolic vector in MATLAB

I have a symbolic vector y which I know contains linear expressions of the variables contained in a symbolic vector theta. Is there a way to compute the symbolic expression of A, where y = A * theta? I tried y*pinv(theta) but it doesn't seem to work.
Example:
syms a b real
theta = [a;b];
y = [2*a;2*b];
y*pinv(theta) gives
ans = [ (2*a^2)/(a^2 + b^2), (2*a*b)/(a^2 + b^2)]
[ (2*a*b)/(a^2 + b^2), (2*b^2)/(a^2 + b^2)]
and
y/theta gives
ans = [ 2, 0]
[ (2*b)/a, 0]
along with a warning that the solution is not unique.
I want to eradicate the symbolic variables from my result i.e. I want
ans = [ 2, 0]
[ 0, 2]
The equationsToMatrix function seems to be doing the job!
Try equationsToMatrix(y,theta)

equationsToMatrix: how do I get the values of the variables?

When using equationsToMatrix you solve a set of linear equations as in the example (the solution is included)
syms x y z;
[A, b] = equationsToMatrix([x + y - 2*z == 0, x + y + z == 1, 2*y - z + 5 == 0], [x, y, z])
%solution of the equation set
A =
[ 1, 1, -2]
[ 1, 1, 1]
[ 0, 2, -1]
b =
0
1
-5
The vector b returns the values of the variables at issue: x,y, and z. However if I type x then MATLAB returns x and not 0, which is the solution of the equation in this case. This also occurs without adding the syms option.
The other problem is that if I type b(1) or b(2), I don't get any value: I would expect b to contain the values of x,y and z.
What I would need is to get something like this in the end
b(1) = 0
or
x = 0
What should I do to get the values of x,y,z by just typing x,y,z?
What you have is a way of converting symbolic linear equations into a numeric system by extracting the coefficient matrices. To solve the system you need to do
sol = A\b;
and now you can use the values in another expression with
subst(expr, {x,y,z}, {sol(1),sol(2),sol(3));
for example
A =
1 1 -2
1 1 1
0 2 -1
b =
0
1
-5
>> A\b
ans =
3.0000
-2.3333
0.3333