A simple algebraic which I failed to do

Hello friends!
Unfortunately, I have to tell you that I am unable to do a simple math I learned at intermediate school in matlab. Consider the following expression
syms dt D0 D1 D2 y y0
f=-(4*D0 - dt*D2 + 4*y*D0^2 - 4*y0*D0^2 + y^2*D2 + y0^2*D2 + 4*y*D1 - 4*y0*D1 - 2*dt*D0*D1 - 2*y*y0*D2 + 2*y^2*D0*D1 + 2*y0^2*D0*D1 - 4*y*y0*D0*D1)/(48*dt^(3/2));
I want to re-write f as in a way that each term has one single coefficient as bellow:
f = (-0.08333*D0 + 0.02083*dt*D2 - 0.08333*y*D0^2 + 0.08333*y0*D0^2 - 0.02083*y^2*D2 - 0.02083*y0^2*D2 - 0.08333*y*D1 + 0.08333*y0*D1 + 0.04167*dt*D0*D1 + 0.04167*y*y0*D2 - 0.04167*y^2*D0*D1 - 0.04167*y0^2*D0*D1 + 0.08333*y*y0*D0*D1)/(dt^(3/2));
where each coefficient is approximated using the vpa command, for instance the first coefficient is vpa(-4/48*4,4)=0.08333.
However, if I directly apply the vpa command it does not do the job correctly as you can see in bellow
vpa(f,4) = -(0.02083*(4.0*D0 - 1.0*D2*dt + 4.0*D1*y - 4.0*D1*y0 + 4.0*D0^2*y - 4.0*D0^2*y0 + D2*y^2 + D2*y0^2 - 2.0*D0*D1*dt - 2.0*D2*y*y0 + 2.0*D0*D1*y^2 + 2.0*D0*D1*y0^2 - 4.0*D0*D1*y*y0))/dt^(3/2)
which is never what I want.
Any idea?
Thanks in advance!
Babak

2 Comments

Mohammad Shojaei Arani’s last Commnent to my now deleted Answer —
But, nobody answered my main problem "Is there a way to release the memory inside a code? something that 'pack' cannot not do". In fact, the reason I was thinking to round my big numbers was due to the fact that matlab was not able to release the memory while my code was running andto fix this extremely annoying problem I had to think how to shorten my text files, by roundin, etc., in order to be able to cope with lost memories. Later, I realized that my idea to round the numbers was not a good.
So, the main problem with matlab is what I said above. I must stress that this is an extremely big caveat for the success and let's say the survival of a programming language and if the developers of the language do not fix this problem researcher will move to other programming languages especially python which is also free!!! Remember the concept of evolution. Those species which cannot fit themselves to the environmental change and conditions will definitely go extinct!
Thanks for all of your helps and good ideas!
Babak
Note —
I deleted my Answer because this discussion is not going anywhere.
The actual problem has to do with stochastic differential equations, not precisely the symbolic toolbox code, and should be restated to address the problem for which a solution is being requested.
.

Sign in to comment.

 Accepted Answer

Walter Roberson
Walter Roberson on 3 Jan 2022
Edited: Walter Roberson on 3 Jan 2022
"Is there a way to release the memory inside a code?"
NO.
"If matlab would have a garbage collector I would not need to bother you."
As I already explained to you, MATLAB does generally have garbage collection. It is not under user control, but it does not generally need to be. I will post evidence in a few minutes that it has garbage collection.
"If you know a way to release the memory within a code (I mean within the for-loop ( the first for-loop) in the first code) then I am done."
MATLAB generally releases memory automatically, soon after it can prove that a given block of memory is no longer being referenced. It is an open question as to whether MATLAB does garbage collection every time memory is released, or not until a certain amount of memory is queued to be released, or if it depends upon the amount of memory that was allocated. MATLAB has a pool of fixed-sized blocks that can exactly substituted for each other -- an array that is not being shared can grow in-place until it reaches the block size, but after that a block for the other pool is allocated. Such blocks can, in theory, be tracked by a simple occupancy bit-map, but memory optimization for variable-length blocks is more complicated.
"Why the command 'pack' only works outside the code?
pack() literally works by saving all of the variables, clearing memory, and reloading the variables. That requires that all of the variables be serializable -- and functions that are in the middle of executing are not serializable.

9 Comments

Evidence that MATLAB has garbage collection, part 1:
N = uint64(30.9*2^30)
N = uint64 33178622362
F = ones(1, N, 'uint8');
Out of memory.
On this online facility, this size of memory rquest is small enough that it does not trigger that "variable larger than configured maximum", but is still larger than the amount of physical memory. If we can create a series of smaller arrays that would add up to more than this much memory if left uncleaned, then that could only happen if there is garbage collection. I need to postpone this to the next comment as I cannot get past an "out of memory" error inside any one comment.
N = uint64(30.9*2^30)
N = uint64 33178622362
D = 8
D = 8
ND = N/D
ND = uint64 4147327795
R = D*2
R = 16
for K = 1 : R
F = ones(1, ND, 'uint8');
F(end) = K; %just to make sure the memory really is occupied
end
fprintf('success, total allocated memory: %ld\n', ND*R );
success, total allocated memory: 66357244720
There, we got through twice as much total memory as was not possible to do in one go. This would not be possible if there was no garbage collection.
Now, you need to stop for a moment and remember that you are using symbolic variables. Where are symbolic variables stored?
A = sym('12345678910111213141516')
A = 
12345678910111213141516
whos
Name Size Bytes Class Attributes A 1x1 8 sym
At this point, you have created a variable A at the MATLAB level, that is associated with a particular symbolic numeric value. Does the symbolic engine know about A as a variable name ??
evalin(symengine, 'A')
ans = 
A
struct(A)
Warning: Calling STRUCT on an object prevents the object from hiding its implementation details and should thus be avoided. Use DISP or DISPLAY to see the visible public details of an object. See 'help struct' for more information.
ans = struct with fields:
s: '_symans_[[32,45,2139]]' mathmlOutput: '<math xmlns='http://www.w3.org/1998/Math/MathML' display='block' xmlns:mw='https://www.mathworks.com/MathML/extensions'>↵ <semantics>↵ <mn>12345678910111213141516</mn>↵ <annotation encoding='OutputVersion'>↵ 1.0↵ </annotation>↵ <annotation encoding='Suggestions'>↵ [{"entryType":"function","ID":"vpa","text":"Approximate numerically","description":"Approximate numerically using variable precision floating point arithmetic","code":"vpa(A)","runOnInsert":true,"nargOut":1},{"entryType":"function","ID":"double","text":"Convert to double","description":"Convert symbolic expression or matrix to MATLAB double","code":"double(A)","runOnInsert":true,"nargOut":1},{"entryType":"function","ID":"diff","text":"Differentiate function","description":"Compute derivative of function with respect to specific variable","code":"diff(A,sym(\"x\"))","runOnInsert":true,"nargOut":1},{"entryType":"function","ID":"fplot","text":"Plot function","description":"Plot function f(x) or expression","code":"fplot(A)","runOnInsert":true,"nargOut":0},{"entryType":"menu","ID":"menuCalculus","text":"Applying calculus functions","description":"Applying calculus functions","children":[{"entryType":"function","ID":"hessian","text":"Compute Hessian matrix","description":"Compute Hessian of scalar with respect to vector","code":"hessian(A)","runOnInsert":true,"nargOut":1},{"entryType":"function","ID":"taylor","text":"Compute Taylor expansion","description":"Compute Taylor polynomial expansion at specific point","code":"taylor(A,sym(\"x\"))","runOnInsert":true,"nargOut":1},{"entryType":"function","ID":"gradient","text":"Compute gradient","description":"Compute gradient of scalar with respect to vector","code":"gradient(A)","runOnInsert":true,"nargOut":1},{"entryType":"function","ID":"limit","text":"Compute limit value","description":"Take the limit of symbolic expression at specific limit point","code":"limit(A,sym(\"x\"),0)","runOnInsert":true,"nargOut":1},{"entryType":"function","ID":"poles","text":"Compute poles of function","description":"Compute poles of symbolic function","code":"poles(A,sym(\"x\"))","runOnInsert":true,"nargOut":1},{"entryType":"function","ID":"series","text":"Compute series expansion","description":"Compute Puiseux series approximation at specific point","code":"series(A,sym(\"x\"))","runOnInsert":true,"nargOut":1},{"entryType":"function","ID":"int","text":"Integrate function","description":"Compute indefinite integral of function with respect to specific variable","code":"int(A,sym(\"x\"))","runOnInsert":true,"nargOut":1}]},{"entryType":"menu","ID":"menuTransform","text":"Computing integral transforms","description":"Computing integral transforms","children":[{"entryType":"function","ID":"fourier","text":"Compute Fourier transform","description":"Compute Fourier transform","code":"fourier(A)","runOnInsert":true,"nargOut":1},{"entryType":"function","ID":"htrans","text":"Compute Hilbert transform","description":"Compute Hilbert transform","code":"htrans(A)","runOnInsert":true,"nargOut":1},{"entryType":"function","ID":"laplace","text":"Compute Laplace transform","description":"Compute Laplace transform","code":"laplace(A)","runOnInsert":true,"nargOut":1},{"entryType":"function","ID":"ztrans","text":"Compute Z-transform","description":"Compute Z-transform","code":"ztrans(A)","runOnInsert":true,"nargOut":1},{"entryType":"separator","ID":"menuSeparator"},{"entryType":"function","ID":"ifourier","text":"Compute inverse Fourier transform","description":"Compute inverse Fourier transform","code":"ifourier(A)","runOnInsert":true,"nargOut":1},{"entryType":"function","ID":"ihtrans","text":"Compute inverse Hilbert transform","description":"Compute inverse Hilbert transform","code":"ihtrans(A)","runOnInsert":true,"nargOut":1},{"entryType":"function","ID":"ilaplace","text":"Compute inverse Laplace transform","description":"Compute inverse Laplace transform","code":"ilaplace(A)","runOnInsert":true,"nargOut":1},{"entryType":"function","ID":"iztrans","text":"Compute inverse Z-transform","description":"Compute inverse Z-transform","code":"iztrans(A)","runOnInsert":true,"nargOut":1}]},{"entryType":"menu","ID":"menuNumber","text":"Plotting functions","description":"Plotting functions, expressions, and equations","children":[{"entryType":"function","ID":"fimplicit","text":"Plot implicit equation in 2-D","description":"Plot 2-D implicit equation or function f(x,y)","code":"fimplicit(A)","runOnInsert":true,"nargOut":0},{"entryType":"function","ID":"fimplicit3","text":"Plot implicit equation in 3-D","description":"Plot 3-D implicit equation or function f(x,y,z)","code":"fimplicit3(A)","runOnInsert":true,"nargOut":0}]}]↵ </annotation>↵ </semantics>↵</math>↵' Digits: 32
No. The name A currently lives only at the MATLAB level. What is inside the symbolic engine is a variable named _symans_[32,45,2139]] and the MATLAB level has been told to refer to that name when it wants to retrieve the value from the symbolic engine.
But we can, if we know how, create a specific variable name inside the symbolic engine
feval(symengine, '_assign', 'ASYM', A)
ans = 
12345678910111213141516
whos
Name Size Bytes Class Attributes A 1x1 8 sym ans 1x1 8 sym
evalin(symengine, 'ASYM')
ans = 
12345678910111213141516
and get it back by name. The reason I did not assign to symbolic variable A inside the symbolic engine was that I wanted to be extra-clear that when I was recalling by name from inside the symbolic engine, that if I referred to A inside the symbolic engine, that there is no connection with MATLAB workspace variable named A. If I had commanded evalin(symengine, 'A') then there would be a risk that you might have though that A was being looked up inside the MATLAB workspace, but with my referring to ASYM instead, you can see from the whos result that there is no MATLAB level variable by that name, and that the name created inside the symbolic engine lives entirely inside the symbolic engine.
clearvars
whos
Now we have removed all of the MATLAB-level variables. Can we still get at the symbolic-level variable if we know its name?
evalin(symengine, 'ASYM')
ans = 
12345678910111213141516
Yes! And if somehow we knew the name _symans_[32,45,2139]] then we could have used that too.
So.... everything that you calculate inside the symbolic engine gets assigned an internal variable name that lives inside the symbolic engine, and MATLAB gets told what the internal name is (but is not told what the value of the variable is -- MATLAB has to specifically ask for the value if it wants the value.) When you change variables at the MATLAB level, perhaps by assigning a new value to A, then the MATLAB level loses track of the internal names at the symbolic level, but those internal variables continue to exist. There are ways to get at a list of all of the symbolic-level variable names if you know the right questions to ask the symbolic engine. So the fact that MATLAB has lost track of a symbolic variable name does not mean that the symbolic engine should be notified to delete the variable. Information about assumptions on variable names crosses MATLAB function boundaries as a deliberate part of the design. Expressions that live inside the symbolic engine are not scoped according to the MATLAB-level scoping rules.
So... things can build up inside the Symbolic Engine, because the Symbolic Engine does not know that you will not need them again. The actual symbolic expressions live in a different process (the symbolic engine), not in the MATLAB process.
I'm glad you brought this up because I've been wondering about this exact topic of what is stored in the symbolic engine. If I understand correctly
syms A t
A = 2*t;
struct(A)
Warning: Calling STRUCT on an object prevents the object from hiding its implementation details and should thus be avoided. Use DISP or DISPLAY to see the visible public details of an object. See 'help struct' for more information.
ans = struct with fields:
s: '_symans_[[32,13,593]]' mathmlOutput: [] Digits: []
So the matlab variable A is mapped to something called _symans_[[32,40,1619]] in the engine. By executing
clear A
all I've done is clear A from the Matlab workspace, but that symans thing is still hanging around in the engine. Is that correct?
If so, what do you mean by "the Symbolic Engine does not know that you will not need them again"? In what use case would I need that symans again and how would I get to it?
I thought maybe something like this would use the same symans, but apparently not.
B = 2*t;
struct(B)
Warning: Calling STRUCT on an object prevents the object from hiding its implementation details and should thus be avoided. Use DISP or DISPLAY to see the visible public details of an object. See 'help struct' for more information.
ans = struct with fields:
s: '_symans_[[32,13,595]]' mathmlOutput: [] Digits: []
As you said, "things can build up inside the Symbolic Engine." Is there any problem with that?
Here is the way to retrieve the internal symbolic engine tags for internally assigned values. Very few people would have reason to do this.... but it is possible.
Why would anyone? Well, if you were writing new symbolic routines, such as if you wanted to extend what differentiation could do, then sometimes you need to know these things.
A = sym('12345678910111213141516')
A = 
12345678910111213141516
struct(A).s
Warning: Calling STRUCT on an object prevents the object from hiding its implementation details and should thus be avoided. Use DISP or DISPLAY to see the visible public details of an object. See 'help struct' for more information.
ans = '_symans_[[32,48,1911]]'
evalin(symengine, 'map(anames(User), expr2text)')
ans = 
evalin(symengine, '[op(_symans_)]').'
ans = 
Darn, the output gets truncated relative to what you can see "live". When you run the code, you can see the symans entry that matches the index given for A and has the content assigned to A.
Thanks. Any thoughts on that last question I had above, repeated here ....
As you said, "things can build up inside the Symbolic Engine." Is there any problem with that?
I would expect problems with memory allocation if you calculate numerous symbolic expressions and return them to the MATLAB level.
You should assume that the Symbolic Engine can do garbage collection on any intermediate results it needs internally, but that once you have returned the expression to the MATLAB level, that you have effectively generated a pointer that will not be released unless you reset the engine with
reset(symengine)
or clear all
Note: there is also a
collectGarbage(symengine)
but it will not clear out the _symans_ table.
Thanks a lot Walter!
I will try the two commands you mentioned to see how they help me to release the memory.

Sign in to comment.

More Answers (0)

Community Treasure Hunt

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

Start Hunting!