How to convert strings to symbolic expressions without sym()?

Since sym() outputs a warning, that it is deprecated to use it with a string input since R2016a as follos:
>> syms x
>> sym('x+1')
Warning: Support of strings that are not valid variable names or define a number will be removed in a future release. To create symbolic expressions,
first create symbolic variables and then use operations on them.
> In sym>convertExpression (line 1536)
In sym>convertChar (line 1441)
In sym>tomupad (line 1198)
In sym (line 177)
Is there a different way to convert a string into a symbolic expression?

 Accepted Answer

y = evalin(symengine, 'x+1')
which does the same thing as
y = sym('x+1')
except that going through sym() has more overhead for this situation and will give you the warning.
Caution: when you use
syms x
sym('x+1')
then the x of the second version does not necessarily refer to the same thing that the first one refers to. For example if you had used
syms x y
x = y + 2
sym('x+1')
then you will not get y + 3

2 Comments

Thanks for the information and the warning!
As an additional warning, this will not use MATLAB syntax (nor pure MuPAD syntax either) and will not work with some variable names, including D, E, I, beta, and will have unexpected effects with some functions such as zeta(a,b) swapping its arguments.

Sign in to comment.

More Answers (3)

Why do you need to convert strings to symbolic expressions? EDIT: Starting R2017b, use str2sym
>> str2sym('x+1')
ans =
x + 1
Karan. (Symbolic documentation)

7 Comments

N = 64;
X = sym(zeros(1, N));
lhs = sym(zeros(1,N));
rhs = sym(zeros(1,N));
for i = 1 : N
X(i) = symfun( sprintf('x%d(t)', i), t );
end
It would be common to expect to be able to use
X(i) = sym( sprintf('x%d(t)', i) );
or at least
X(i) = symfun( sym(sprintf('x%d(t)', i)), t );
in order to get the symbolic functions x1(t), x2(t) and so on. But you cannot do that without a warning, because sym() now complains if you feed it an expression that is not a pure number or a pure name. I had to take advantage of the fact that symfun() will still accept a string directly, which is something that we can predict will not continue to be the case in future releases because you expect everyone to start using just pure symbols and pure names and manipulate them.
Not shown there was how much effort I put in to trying to be able to dynamically construct a symbolic function which would actually display as a function and act as a symbolic function. It turned out to be impossible: I could construct the function as a symbolic expression (sym object) but I could not "bless" it into being a symbolic function (symfun object) because the appropriate property is private to the symfun constructor.
Using the symfun() routine is not appropriate because symfun() is not for creating procedures. symfun() fully evaluates its first input and then extracts symbolic variables from that result to become the arguments. Try, for example, constructing the symbolic function
f(x) = mod(x,1)
You might be tempted to use
syms f(x)
f(x) = mod(x,1);
or
syms f(x)
f(x) = symfun(mod(x,1), x)
but what you will get is f(x) = 0 -- because the mod(x,1) is fully evaluated and mod(some_symbol,1) evaluates to 0 .
You cannot even do it by hand by calling into MuPAD
>> class(evalin(symengine,'x->_mod(x,1)'))
ans =
sym
The above is a sym not a symfun. If you attempt to invoke it with an argument, MATLAB will think you are indexing.
>> f(x) = evalin(symengine, 'proc(x) begin _mod(x,1) end_proc')
f(x) =
Warning: The result cannot be displayed due a previously interrupted computation or out of memory. Run 'reset(symengine)' and rerun the commands to regenerate the
result.
> In sym/disp (line 42)
In sym/display>displayVariable (line 83)
In sym/display (line 47)
That's just broken.
And, No, you cannot get it to work by using enough hold()
Before you get rid of the notebook interface you need to be able to dynamically create functions in MATLAB, especially ones that can take advantage of the MuPAD library functions such as numeric::ode. The created functions need to be able to bind their parameters before evaluation. You need the equivalent of the MuPAD hold() facility so you could at least do something like
f(x) = symfun( symhold(mod(x,1)), x)
where the mod(x,1) must not get evaluated. But of course that violates the MATLAB execution model where all arguments get evaluated except inside an anonymous function definition.
Perhaps symfun could be extended so that symfun() applied to an anonymous function constructed a symfun with the same arguments, such as
symfun( @(x) mod(x,1))
That would help, but is probably not enough.
Hi Walter,
Your problems with creating symfun are not caused by the constructor somehow keeping things private – symfun are a completely different thing from MuPAD functions and will always simplify/evaluate the formula/function body. Basically, a symfun is a standard sym with the addition of function call syntax that performs a subs call. (Which in MATLAB means hiding the subscripting that would use the same syntax, so a symfun necessarily is scalar, even if it returns a non-scalar value.)
If you do not want the body simplified, what you are looking for is probably closer to a standard MATLAB function and I would implore you to use one instead, simply saying @(x) mod(x,1) as you did in your last example. Why try to put that into a symfun?
As for the 'x%d(t)' example, I'd like to offer a workaround, which admittedly is a bit arcane/hackish as well:
>> syms f(x)
>> subs(f,'f',sym('g',[1,3]))
ans(x) =
[ g1(x), g2(x), g3(x)]
"Your problems with creating symfun are not caused by the constructor somehow keeping things private – "
>> syms foo(x)
>> isa(foo,'sym')
ans =
logical
1
So symfun are sym. The property that cannot be set from outside the sym parent class is "vars". The presence or absence of that property determines the display style, but the subclass symfun does have a different method for () indexing. disp() of the two goes through the same code.
I would need to retrace the exact failure mode for displaying generated functions.
True, symfun are sym. As usual in OO land, that does not mean that every sym has all the properties a symfun has. (E.g., a java.io.File instance is a java.lang.Object, but not every object in Java has a getPath method. Is-a is a non-symmetric relation.) A symfun being a sym means that you can use a symfun where a sym is expected (and some code somewhere may have limitations on that, of course), not the other way round.
In particular, sym do not have a vars property (hidden or otherwise), and if they did, that would just be an immaterial implementation detail, just like the name of the property is in the first place. Or the fact that currently symfun does not define its own output—irrelevant and subject to change without notice.
I'll just point to your own comment on how to “set "vars",” i.e., how to create a symfun. No need to repeat what you already said.
None of that changes the basic behavior, however, that unlike in a MuPAD (or MATLAB) function, a symfun cannot have an unsimplified formula such as x->x mod 2 or @(x) mod(x,2) does. Maybe there is a reason somewhere to do that (in which case we'd have to consider adding such a tool, and that would probably then not be a child class of sym), but I don't see any of your examples requiring it yet. @(x) mod(x,1) seems to work just fine here.
You can't differentiate an anonymous function for one thing.
Why offer symfun at all?
By the way, why is mod(x, 1) = 0 for symbolic x? mod(x, 2) returns unevaluated
You can't really differentiate a function without simplifying it, either. Well, technically you probably could, in a lot of cases, but I doubt that most of the code SMT has for differentiating would care about noncommutativity and such, likely reasons for not wanting a simplified formula. Nor does the system have any idea how to differentiate mod.
The same would be true for solve and int as well, and most other functions. Such an extension would be absolutely nontrivial.
The prime reason for symfun, to me, is to specify the order of variables, followed closely by having a simpler syntax for subs. These reasons are very different from the reasons for having functions in MuPAD, so it's not a surprise the resulting design is different.
mod(x,2) returns x for me, as expected. (I do realize my expectations may be different from anyone else's and colored by knowing what the function does to start with.) mod(3*x,2) returns x, too, because mod(3,2) is 1, and mod(1.5*x,1) returns x/2 for pretty much the same reason. This is explained in the third example in doc symbolic/mod.
My reasons for constructing symbolic functions are often similar to to the reasons for having functions in MuPAD: which is to say that I am constructing something procedural that involves symbolic expressions.
Recently someone was computing things with terms equivalent to sinc() and asked how to rewrite them in terms of an explicit sinc() instead of in terms of sin(pi*x)/(pi*x) . The position of the sin() in the expression was not fixed. I was not able to get subs() to replace sin() calls
>> subs(sin(pi*x)+x, 'sin', 'SIN')
ans =
x + sin(pi*x)
and I was not able to get feval(symengine) to do a subs() for this case either. I could get feval(symengine) of subsop() to do something, but that required knowing which operand number to substitute.
Now, if I could write symbolic functions that could bind parameters and use op() and pattern matching and local variable names (normal MATLAB level symbolic variables are effectively global, inheriting any assume() that has been done at any level)...

Sign in to comment.

syms x
y = x+1;
WTP? No warning. No problem.

1 Comment

That does not convert a string to a symbolic expression. I am aware, that it is possible to directly enter the symbolic expression.

Sign in to comment.

You can do that by using sub function as follows (Simple trick) :
example : f(x) = x+1 ;
if you input f as string >> f = 'x+1'
then use sub to substitute the value ex. 1
subs(f,'x',1)
So , matlab will deal with it as function wihtout any wrong message
then the answer will be :
2

2 Comments

The above is not valid since R2018a. From R2017b you should use str2sym()
you might right.
I am using version 2016b

Sign in to comment.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!