Do Orphaned sym Objects in the Symbolic Engine Matter?

Suppose I execute the following code
func
a. Did I just create an object in the symbolic engine that I have no way to access?
b. If so, is that object an orphan in the sense that I can't access it for any subsequent commands in the base workspace?
c. Or, is there a way that the object in the symbolic engine can be 'poofed' back into a symbolic object in the base workspace?
d. If so, can that happen without me knowing about it?
e. Is there anyway for the exsistence of that object in engine and its associated assumption to have any silent impact on subsequent symbolic computations?
f. Can I count on other functions, like @doc:solve in the parameters output argument, that create objects in the engine, to not be affected by the existence of the orphaned object? For example, the symbolic variable in parameters is typically called 'k' if it's an integer. Will there be a problem if the orphaned object is named 'k'? Or will parameters use a different variable?
The more I think about it, the more I think that symengine orphans must be a non-issue, because I can do something as mundane as
f = sym('x') + sym('y');
f = 
clear f
after which the Matlab variable f is no lonnger in the base workspace, but x and y are still hanging around in some form in the engine, aren't they? In other words, orphans can arise all the time, so (hopefully) shouldn't be a problem.
function func
sym('z','positive');
end

 採用された回答

Walter Roberson
Walter Roberson 2023 年 12 月 24 日

0 投票

func
assumptions()
ans = 
z = sym('z')
z = 
z
assumptions()
ans = 
syms z
assumptions()
ans = Empty sym: 1-by-0
function func
sym('z','positive');
end
So, no you did not create an orphan object: you can get it back with sym() (but not syms() )

10 件のコメント

Walter Roberson
Walter Roberson 2023 年 12 月 24 日
Yes, the existence of a symbolic variable can affect future calculations. When it comes to assumptions there is no such thing as a local symbolic variable.
syms z positive
assumptions()
ans = 
func()
ans = 
z
assumptions()
ans = 
function func
sym('z', 'integer')
end
Walter Roberson
Walter Roberson 2023 年 12 月 24 日
On the other hand, there is no interference with the value of symbolic variables.
syms x
z = x + 5;
assumeAlso(z, 'positive')
z
z = 
assumptions()
ans = 
func()
z
z = 
assumptions()
ans = 
function func
syms z integer
end
Steven Lord
Steven Lord 2023 年 12 月 24 日
If you must reset the symbolic engine, you could call clear all or (if that's too big a hammer) you could call reset on the output of the symengine function (even though it's not recommended.)
func
assumptions()
ans = 
clear all
assumptions()
ans = Empty sym: 1-by-0
func
assumptions()
ans = 
reset(symengine)
assumptions()
ans = Empty sym: 1-by-0
Or if you want to clear assumptions on a variable, just define it with no assumptions in this workspace.
func
assumptions()
ans = 
syms y
assumptions()
ans = 
function func
syms z positive
syms y integer
end
Paul
Paul 2023 年 12 月 24 日
編集済み: Paul 2023 年 12 月 25 日
Based on how on what I now see, the answers to my own questions, and some follow-ups:
a. 1) Did I just create an object in the symbolic engine that 2) I have no way to access?
1) Yes, an obeject yas been created in the engine. 2) No, it can be accessed in the base workspace (and presumably in other workspaces, like a function workspace) using sym().
b. If so, is that object an orphan in the sense that I can't access it for any subsequent commands in the base workspace?
Not an orphan, it can be brought back into play, so to speak, using sym().
c. Or, is there a way that the object in the symbolic engine can be 'poofed' back into a symbolic object in the base workspace?
it can be brought back into play, so to speak, using sym().
d. If so, can that happen without me knowing about it?
I'm still not sure about this.
e. Is there anyway for the exsistence of that object in the engine and its associated assumption to have any silent impact on subsequent symbolic computations?
Yes, if z is brought back into a base workspace expression, then all assumptions on z will apply.
f. Can I count on other functions, like solve in the parameters output argument, that create objects in the engine, to not be affected by the existence of the orphaned object? For example, the symbolic variable in parameters is typically called 'k' if it's an integer. Will there be a problem if the orphaned object is named 'k'? Or will parameters use a different variable?
Looks like solve is smart enough if it's called after (are there any other functions to be concerned about it in this regard?):
clear all
syms x
sol = solve(sin(x*sym(pi))==0,'ReturnConditions',true) % k is the parameter
sol = struct with fields:
x: k parameters: k conditions: in(k, 'integer')
clear all
func_k % creates k in the engine with an assumption
assumptions
ans = 
syms x
sol = solve(sin(x*sym(pi))==0,'ReturnConditions',true) % k is NOT the parameter
sol = struct with fields:
x: l parameters: l conditions: in(l, 'integer')
As may be obvious, my question is really getting at how to properly/correctly/safely use the Symbolic Math Toolbox functionality in m-functions (actually, I think we've had a discussion about this already in a different thread, so I apologize if I'm rehashing old ground). It seems like the basic issue is that base and function workspaces are local, but the symbolic engine is global. So, whenever a sym object is created in a function or an assumption is made in a function, there is a risk that the function will alter something in the engine that has already been or will later be defined in the calling workspace.
I suppose one option is to have the user create all variables with all assumptions in the base workspace, and then pass those variable in as input arguments into the function. I can see this as a viable, though unpalatable, approach for simple functions, but not so sure how well that will work for extensive programs.
I guess another option would be to create sym objects locally in the function workspace with names that are very unlikely to collide with objects that already exist in the engine. This appoach may be tenable, but doesn't sound palatable for extensive programs.
A third option would be to use functionality that looks like solve already has. That is, have the ability to check for the existance of an object in the engine, and then take appropriate action locally if that object already exists. How does solve do that?
function func_k
sym('k','real');
end
Walter Roberson
Walter Roberson 2023 年 12 月 24 日
You can record the current assumptions and reactivate them later
syms x positive
z = x + 5;
assumeAlso(z > 0)
held_assumptions = assumptions()
held_assumptions = 
syms x
assumptions
ans = Empty sym: 1-by-0
assume(held_assumptions)
assumptions
ans = 
Paul
Paul 2024 年 1 月 7 日
That's a good idea. I can use symvar on the assumptions to find the variables that have assumptions set.
syms a b c x y z real
vars = symvar(assumptions)
vars = 
The next step would be to create a symbolic variable that's not one of a, b,c, x, y, or z. Any thoughts on how to do that (besides using esoteric variable names)?
I suppose I could set up a list of variable names
varnames = char(97:122);
And then find one that's not in vars
for ii = 1:numel(varnames)
if ~ismember(sym(varnames(ii)),vars)
break
end
end
myvar = sym(varnames(ii))
myvar = 
d
Then my function returns expressions in terms of d, which at least is guaranteed to not have any assumptions on it at the time of the function return.
You do not need to create a symbolic variable that is not one of the uses ones: you can just record the current assumptions, proceed with your calculations, and then restore the assumptions.
%remember assumptions
held_assumptions = assumptions();
%do some work with random variables
syms x positive
z = x + 5;
assumeAlso(z > 0)
assumptions
ans = 
%restore assumptions
assume(held_assumptions)
Paul
Paul 2024 年 1 月 7 日
If the function is to return a symbolic expression, I don't want any of the sym variables in that expression to be subsequently affected by the restored assumptions.
Walter Roberson
Walter Roberson 2024 年 1 月 7 日
When you
syms x
that is equivalent to first telling the symbolic engine that you are interested in a variable named x, and then resetting any internal symbolic engine assumptions associated with x, and returning an abstract reference to x out of the symbolic engine, then storing the abstract reference in a sym object, and lastly assigning x at the MATLAB level to be the sym object.
Then as you use x then the sym object is consulted to get the abstract internal reference, the abstract internal reference is passed to the symbolic engine along with instructions to perform whatever operation, returning an abstract reference out that gets wrapped in a sym object and the sym object gets returned.
z = x + 1;
results in z at the MATLAB level being a sym object that contains an abstract reference such as '_symans_[[32,0,36]]' -- without creating any variable z at the symbolic level.
As long as you do not call evalin(symengine) or feval(symengine) yourself, the variables that live at the level of the symbolic engine are restricted to what you have syms or sym or symmatrix into existence, together with the automatically created variable z that is used in rootOf structures, and variables automatically created by solve() to hold parameters. And as long as you do not call evalin(symengine) or feval(symengine) yourself, variables at the symbolic engine level just hold information about their names and assumptions.
x = x + 1;
would result in x at the MATLAB level being a sym object that holds an internal reference such as '_symans_[[32,0,38]]' and that internal reference would be to _plus(x,1) . If you were to
x = x + 1;
again then x at the MATLAB level would become a sym object that holds an internal reference such as '_symans_[[38,0,143]]' and that internal reference would be to _plus(x,2)
Under the restriction that you do not call evalin(symengine) or feval(symengine) yourself then the symbolic engine will hold only simple variable names that represent themselves -- together with a bunch of anonymous expressions known only by their _symans_ references. The MATLAB level holds the _symans_ references.
f = sym('x') + sym('y');
There is no symboic variable named f at the symbolic engine level -- there is just x and y and there is a _sysmans_ representing the expression _plus(x,y)
Because of this, the only thing you can do that affects "the real x" that is held in the symbolic engine is to change the assumptions associated with it. No matter how complicated of an expression you build up, the symbolic engine level will only know simple variables x and y (and other variables you sym() or syms() into existence) and everything else is a _symans_ at the symbolic engine level. f = sym('x') + sym('y') will absolutely not result in a symbolic variable f being created a the symbolic engine level.
So.... you can play around with variables as much as you want inside of functions, and at most you will affect the assumptions on variables and possibly pop a few more variables into (simple) existanence . The rest is all _symans_ stuff. If you previously had f = sym('x') + sym('y') in effect and in a function you do f = exp(sym('x')) then you get a _symans out that is written into a local MATLAB variable f and absolutely nothing about the previous expression is affected. If you restore the assumptions and then return from the function, everything is fine.
(How garbage collection is done on the various _symans_ is an excellent question; I do not know the answer.)
Paul
Paul 2024 年 1 月 8 日
What I meant is a situation like this.
syms z positive
Now call a function that does something and returns a symbolic expression
h = myfunc()
h = 
assumptions
ans = 
The expression returned from the function is now subject to the assumptions on z made in the base workspace, even if those assumption were temporarily removed in the function and weren't intended to apply to the returned expression.
solve(h)
ans = 
1
It seems like the only way to avoid this is to make sure that the returned expression doesn't depend on any of the assumptions made outside the called function.
function f = myfunc()
held_assumptions = assumptions;
assume(assumptions,'clear')
z = sym('z');
f = (z-1)*(z+1);
assume(held_assumptions)
end

サインインしてコメントする。

その他の回答 (0 件)

カテゴリ

ヘルプ センター および File ExchangeSymbolic Math Toolbox についてさらに検索

製品

リリース

R2023b

質問済み:

2023 年 12 月 24 日

コメント済み:

2024 年 1 月 8 日

Community Treasure Hunt

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

Start Hunting!

Translated by