Extract operations from symbolic expression

Hello,
given a symbolic expression, I want to extract the fundamental operations that take place in this symbolic expression. In the end, I want to create a Simulink model that does the same as the symbolic expression but without a simple matlab function block but with basic simulink blocks. For that, I need to know what happens to the inputs and in what order.
For example:
I have the symbolic expression z = cos(x)*y + y^2.
How exactly do I get the necessary information from the sym object? I want to extract that the cosine of x is computed which is then multiplied with y and then this product is added to the square of y.
Are there any built-in function that can help me with this? So far, the only solution I could think of was to parse the string generated by "simscapeEquation(z)"
Thanks so much!

2 Comments

If you have
z = cos(x)*y + y^2/cos(x)
then what would the desired output look like? For example are you hoping for a stream of RPN operations such as might be used for an HP29c calculator, with code like
x COS DUP y DUP SWAP2 * SWAP DUP * SWAP2 / +
? This specifies the stream of operations (and is at least partially optimized... I would have to think about whether you could do better by entering y first)
I'm not yet sure how the output should look like. I discovered that the Shunting yard algorithm at least brings the operation in the right order so that you can read it from left to right. But yes, a stream of RPN operations would be a good starting point

Sign in to comment.

 Accepted Answer

Hi Cedric
What's the objection to using a Matlab Function block? If that wasn't a constraint, you could use matlabFunctionBlock
Even if you break down the expression, what would be the next step for implementing all of the individual Simulink blocks to rebuild the expression in Simulink?

5 Comments

The objection is that in our developing enironment (we're designing flight controllers) matlab function blocks are simply not allowed and I can't really anything about it. If I broke down the equation into its fundamental operations, I could write a function that automatically builds the equivalent simulink model. But that's a problem for another day
That's a good reason. Maybe you can proceed along these lines:
syms z x y
z = cos(x+1)*y + y^2 -(x+2)^2 -y/4 + 4*x*y
z = 
z = expand(z,'ArithmeticOnly',true)
z = 
symvar(z)
ans = 
So we know our Simulink Subsystem block needs two inputs, one for x and one for y.
I think children gives precedence to addition
c = children(z)
c = 1×7 cell array
{[-4*x]} {[-y/4]} {[y*cos(x + 1)]} {[4*x*y]} {[-x^2]} {[y^2]} {[-4]}
We need a Sum block with 6 inputs.
Now, in theory, we could procced recursively through each element of c and figure and keep using children to get finer and finer details on the signal. hasSymType will be helpul to break down each sub-expression based on it operators and functions, which can then be mapped to Simulink blocks, all the while keeping track of the connections.
children does not give priority to anything in particular; it has access to the internal parse tree and just returns the child nodes of the given expression.
The representation of symbolic expressions is as a list. The list starts with a type tag; in a few cases the type tag is enough to fully determine the value of the object. If not, then the next item in the list may be a value (for example for an integer object. In the case of operations or function calls, the second value in the list (after the tag) is the link to the function name node, and values after that are the operands.
For example, cos(x) + y^2 could coded as the tree _plus(cos(x), _power(y,2)) and that can lead to OBJECT1: [EXPRESSION, cos, x], OBJECT2: [EXPRESSION, _power, y, 2], OBJECT3: [EXPRESSION, _plus, OBJECT1, OBJECT2]
and when you do children() on object3 it just throws away the EXPRESSION and function name, and returns a list of the remaining operands. children(OBJECT3) --> [LIST, OBJECT1, OBJECT2], and children(OBJECT2) -> [LIST, y, 2]
The MATLAB level gets returned back the LIST and converts it to a cell array.
Anyhow:
Instead of hasSymType you would probably want symFunType()
syms y f(x)
z = cos(x) + f(y^2)
z = 
symFunType(z)
ans = "plus"
cellfun(@symFunType, children(z), 'uniform', 0)
ans = 1×2 cell array
{["f"]} {["cos"]}
Notice how the unknown function f got returned as the "type" of the expression f(y^2)
Paul
Paul on 29 Jan 2023
Edited: Paul on 11 Feb 2023
Yes, symFunType is what would be needed. Don't know how I didn't see that.
Assuming the original expression can be implemented in Simulink in the first place ....
One feasible apprroach may be to use symvar to find out the inputs to the epxression and create inport blocks for those, and create an outport block for the output
Then recurse as follows:
Check the symFunType of the expression.
Map the result to the a Simulink library block and add it to the model.
Determine if the expression has additional children that need to processed.
All while keeping track of the parent block to to which the children blocks need to be connected.
Don't know if that will really work, but it seems like it might.
The children and the symFunType command was exactly what I needed, thank you! I actually made it work now :)

Sign in to comment.

More Answers (0)

Categories

Find more on General Applications in Help Center and File Exchange

Products

Release

R2021a

Tags

Asked:

on 28 Jan 2023

Edited:

on 11 Feb 2023

Community Treasure Hunt

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

Start Hunting!