MATLAB: Conversion to logical from sym is not possible - matlab

I'm having a problem with a user defined function I am constructing here. What I'm trying to do is to substitute a value into a symbolic function and then use that numerical answer for various purposes. Specifically here:
x = xo;
subst = subs(f,x);
while((n>i) && (subst > eps))
Running my program, I get the following error:
>> sym_newtonRaphson(f,fdiff,1,1e-8,10)
Conversion to logical from sym is not possible.
Error in sym_newtonRaphson (line 8)
I've tried using double(subs(f,x)) to no avail. I seem to be getting a totally different error relating to MuPAD (DOUBLE cannot convert the input expression into a double array.)
The following is the whole program:
function [output] = sym_newtonRaphson(f,fdiff,xo,eps,n)
i = 0;
%initial iteration
x = xo;
subst = subs(f,x);
while((n>i) && (subst > eps))
x = x - (subs(f,x))/fdiff;
i = i+1;
subst = subs(f,x);
%fprintf('%f\t%f\t%f\t%f\t%f\t%f',i,alpha,f(
end
output = x;
end
I'd appreciate some pointers as to what I'm doing wrong; all the best.

What you're trying to do with the while expression is equivalent to logical(f), where f is a symbolic function (rather than a symbolic value). logical(sym('exp(1)') > 0) is fine, but logical(sym('exp(f)') > 0) is generally not going to be (see assume). Matlab has no way of casting a symbolic variable to a logical (true and false) one. It tries to do this because the short circuit AND operator, &&, isn't supported for symbolic variables. For example
a = 1.5;
syms x;
% All of these will not generate errors
y1 = x > 1;
y2 = x > 1 & x < 2;
y3 = x > 1 & x < 2;
y4 = x > 1 & a < 2;
y5 = x > 1 & a > 2;
% These will result in errors
y2 = x > 1 && x < 2;
y3 = x > 1 && x < 2;
y4 = x > 1 && a < 2;
y5 = x > 1 && a > 2;
You should print out subst and make sure that it is a symbolic value or a function that does not include any variables (if argnames(subst) returns an empty symbolic matrix then you should be okay). The fact that you get the second error when you call double seems to imply that subst is actually an expression that still includes unknown variables. If this is the case, then you'll either need to substitute in other variables or use assumptions (see here) in order to do logical comparisons as you're doing.

Related

MATLAB solve() returns array for linear equation

I have the following equation in MATLAB:
eqn1 = (1-t)*x1 + t*x2 == x; where x1,y1 = <some_constant_value>
I am solving the equation as:
t1 = double(solve(subs(eqn1,x,min(x_arr(i,:))),t)); and doing a comparison as:
if(t1 >= 0 & t1 <= 1)
crossing = 1;
return
end
However, from time to time, I get the following error:
Operands to the || and && operators must be convertible to logical scalar values.
From what I found out on other forums/answers, this is because && and || is not capable of handling arrays and hence, the error. But, considering I am solving a linear equation, why is MATLAB returning an array?
EDIT
My apologies, I forgot to give the initialization for the variables:
syms x y t
x1 as double
x2 as double
y1 as double
y2 as double
x_arr as double
y_arr as double
I got it working in a hacky manner by splitting the if conditions as:
if(t1 >= 0)
if(t1 <= 1)
crossing = 1;
return
end
end

Solving a piecewise function for a given intercept in Matlab

I'm trying to solve a piecewise function, but I am getting an error. The following is the code.
script:
syms x
y_intercept = 2;
answerr = solve(pw_f(x) == y_intercept, x);
piecewise function (in a separate file within the same folder):
function y = pw_f(x)
if x < 0
y = x;
elseif (x >=0) && (x <= 20)
y = 2*x;
elseif x > 20
y = 4*x - 40;
else
end
end
The error I'm getting after running the script is:
Conversion to logical from sym is not possible.
Error in pw_f (line 3)
if x < 0
Error in solve_test
answerr = fsolve(pw_f(x) == y_intercept, x);
I know that the error is because Matlab can't perform the comparison x < 0 because x is a symbolic variable, so it does not know what x is yet. I also tried using fsolve, and vpasolve but I'm still getting the same error. Do you know how to solve this in Matlab or get around this error?
Of course, this is an easy problem that I can do in my head (x = 1 is the solution) so Matlab should be able to do this!! However, I want to make this generic for any y-intercept (maybe some random number that is not such a nice whole number) that I choose. PLEASE HELP!!!! Thanks :)
FYI, I am using Matlab R2013a.
In file called pw_f.m
function y = pw_f(x)
if x < 0
y = x;
elseif (x >=0) && (x <= 20)
y = 2*x;
elseif x > 20
y = 4*x - 40;
else
end
end
In command window
>> y_intercept = 2; % set object value
>> x0 = 0; % initial guess
>> answerr = fzero(#(x)pw_f(x) - y_intercept, x0) % solve
answerr =
1
>> pw_f(answerr) % test solution
ans =
2

Plotting own function in scilab

Hey i have an issuse with plotting my own function in scilab.
I want to plot the following function
function f = test(n)
if n < 0 then
f(n) = 0;
elseif n <= 1 & n >= 0 then
f(n) = sin((%pi * n)/2);
else
f(n) = 1;
end
endfunction
followed by the the console command
x = [-2:0.1:2];
plot(x, test(x));
i loaded the function and get the following error
!--error 21
Invalid Index.
at line 7 of function lala called by :
plot(x, test(x))
Can you please tell me how i can fix this
So i now did it with a for loop. I don't think it is the best solution but i can't get the other ones running atm...
function f = test(n)
f = zeros(size(n));
t = length(n);
for i = 1:t
if n(i) < 0 then
f(i) = 0;
elseif n(i) <= 1 & n(i) >= 0
f(i) = sin((%pi * n(i)/2));
elseif n(i) > 1 then
f(i) = 1;
end
end
endfunction
I guess i need to find a source about this issue and get used with the features and perks matlab/scilab have to over :)
Thanks for the help tho
The original sin is
function f = test(n)
(...)
f(n) = (...)
(...)
endfunction
f is supposed to be the result of the function. Therefore, f(n) is not "the value that the function test takes on argument n", but "the n-th element of f". Scilab then handles this however it can; on your test case, it tries to access a non-integer index, which results in an error. Your loop solution solves the problem.
Replacing all three f(n) by f in your first formulation makes it into something that works... as long as the argument is a scalar (not an array).
If you want test to be able to accept vector arguments without making a loop, the problem is that n < 0 is a vector of the same size as n. My solution would use logical arrays for indexing each of the three conditions:
function f = test(n)
f = zeros(size(n));
negative = (n<0);//parentheses are optional, but I like them for readability
greater_than_1 = (n>1);
others = ~negative & ~greater_than_1;
f(isnegative)=0;
f(greater_than_1)=1;
f(others) = sin(%pi/2*n(others));
endfunction

Creating a user-defined function with conditions on input (x,y) in matlab

I am trying to create a function which takes input (x,y). The function is for the four sides of square x=0, x=1 and y = 0, y=1
The function value is zero on three sides and =k on the fourth side. I create this code for the function:
function f = func_bc(x,y)
if x==0 && y>=0
f = 0;
elseif y==0 && x>=0
f = 0;
elseif y==1 && x>=0
f = 0;
elseif x==1 && y>0
f = k;
end
end
However this does not work when I give a vector as input using feval:
x = meshgrid(0:0.01:1);
y = meshgrid(0:0.01:1);
a = feval(func_bc,x(2:101,1),y(2:101,1));
The error is:
Operands to the || and && operators must be convertible to logical scalar values.
How do I create such a function?
You should be using & and | instead of && and ||. The double operators would be used if x and y were single scalar values. The single operators must be used when either side of the relation is a vector, as in your case.
replace && with &.
Does this do what you need?
function z = mysquare(x,y)
k = 10;
z = zeros(size(x));
z(x==1 & y>0) = k;
>> [X,Y] = meshgrid(0:0.1:1, 0:0.1:1);
>> Z = mysquare(X,Y);

What is wrong with this matlab function code?

I am not sure why this code wouldn't run. PLEASE HELP
function y = PdfMixUnfmBeta(x,alpha)
if x < 0
y = (1-alpha).*1/2;
elseif x >= 0
y = (1-alpha).*1/2 + alpha.*6*x*(1-x);
end;
when I execute this function as follows, there is an error
EDU>> x=-1:0.01:1;
EDU>> a=PdfMixUnfmBeta(x,0.4)
Error in PdfMixUnfmBeta (line 2)
if x < 0
The problem with your function is that you have written it assuming that x is a single value, and then you have passed it a vector. Your code cannot cope with this.
If you try to run your code with a single value, eg: a=PdfMixUnfmBeta(15,0.4) your function should run.
Lets look at what is actually wrong with your code, when I tried running your code I was given the following error:
Output argument "y" (and maybe others) not assigned during call
This indicates that the lines which assign to y are never actually executed. This indicates that neither of the conditional statements (x < 0 and x >= 0) ever evaluate as true. The if statements expects a scalar logical value, but in your example it is provided with a vector of logical.
So, to fix this you either need to deal with your x values one at a time by wrapping it in a for loop, e.g.:
function y = PdfMixUnfmBeta(x_vec, alpha)
for x = x_vec
%do your function here
end
end
Alternatively, you can vectorize your code, which is by far the preferable solution:
y = zeros(1,length(x));
% where x is < 0 use this formula
y(x < 0) = (1-alpha) .*(1/2);
% where x is >= 0 use this formula instead.
y(x >= 0) = (1-alpha) .* (1/2) + (alpha .* 6 .* x .* (1-x));
In the above solution I use logical indexing and change some of the * to .*. You may find it useful to look up the difference between * and .* and to read up on vectorization.