vpa not reducing the precision

Hello,
I am doing some symbolic calculations. Matlab is returning rediculously small numbers up to the order of -180 ! I tried the suggested usage of digits and vpa but none seem to do the job. here is an example of numbers up to -15 .
[ -15 -15 -15 ]
[1. 0.1224 10 -0.1224 10 0.1224 10 q2 + 1. q1]
This is a very simple homogeneous transformation of a frame in multi-body system. you can imagine multiplying these small numbers to get even smaller ones. This is keeping the symbolic variables q1, q2 ... in the experession and further complicating the calculations and slowing down the program.
I ran vpa on these results, it didn't work. I went down and applied vpa on every symbolic math in my sheet, still didn't work.
please adivse..
thanks.

3 Comments

Can you show us your full code? Your expectations.
EngM
EngM on 11 Feb 2022
Edited: KSSV on 11 Feb 2022
Here we go..
%This is a class definition of a Link defined in DH format
classdef LinkRecord
%DH Link Recrod
properties
% a =1;
% alpha =0;
% d =0;
% theta =0;
type {mustBeText , mustBeMember(type,{'revolute','prismatic','fixed'})} = 'revolute'
parent {mustBeNumeric} = 0;
TtoP = HTransfer(eye(3),zeros(3,1));
TtoB = HTransfer(eye(3),zeros(3,1));
path = [0 1];
name {mustBeText} = 'link'
end
methods
function obj = LinkRecord(tb,type,parent,name)
Rzz = @(alpha) vpa([cos(alpha) -sin(alpha) 0;sin(alpha) cos(alpha) 0;0 0 1]);
Rxx = @(alpha) vpa([1 0 0 ;0 cos(alpha) -sin(alpha);0 sin(alpha) cos(alpha)]);
HTransferr = @(R,p)vpa([[R;0 0 0] [p;1]]);
digits(4);
if iscell(tb)
obj.TtoP = vpa(HTransferr(Rzz(tb{4}),[0;0;tb{3}])*HTransferr(Rxx(tb{2}),[tb{1};0;0]),3);
else
obj.TtoP = vpa(HTransfer(Rz(tb(4)),[0;0;tb(3)])*HTransfer(Rx(tb(2)),[tb(1);0;0]),3);
end
obj.TtoB = obj.TtoP;
% obj.a = tb(1);
% obj.alpha = tb(2);
% obj.d = tb(3);
% obj.theta = tb(4);
obj.type = type;
obj.parent = parent;
obj.path = [0 1];
if ~exist('name','var')
% third parameter does not exist, so default it to something
obj.name = 'link';
else
obj.name = name;
end
end
end
end
thanks..

Sign in to comment.

 Accepted Answer

Consider:
1
10^-49 * --------
x*10^-50
This is, of course, mathematically the same as x*10 -- but there are cases where MATLAB prefers to factor out constants even though it makes other constants "awkward" . Imagine for example 10*y + 10^-14*x then you could imagine that MATLAB might prefer to rewrite that in terms of x first and y, and might prefer to have small-integer coefficient for x by factoring it out, 10^-14 * (x + 10^15*y) . MATLAB does prefer to have the symbols of a summand appear in lexographic order, except in denominators in which case it prefers the first non-negative symbol to be first... and it is prepared to invent multiplications and divisions to reach its preferred internal factorization form.
The point is that Yes, there are definitely cases where MATLAB will factor out into large numbers times small coefficients... cases that are mathematically the same but involve coefficients with small magnitude.
Now imagine that vpa() had the role of going in and zeroing coefficients that were smaller than 1/10^Digits . Then for that first expression, it would be doing 10^-49 * 1/((ZERO the 10^-50) * x) ... which would be 10^-49 * 1/(0 * x) -->> 10^-49 / 0 --> +infinity
Therefore, vpa should not be zeroing "small" coefficients: those small coefficients might be very necessary in context.
You could, I am sure, imagine formulae that involve dividing by Avogadro's Number 6.022*10^23 -- and mathematically that division would be equivalent to multiplying by the reciprical of the number... so multiplying by about 1.6605*10^-24 . If vpa() automatically zeroed "small" constants then that would drastically change the meaning of the expression.
This does not mean that there is no way of getting MATLAB to zero out "small" numbers... but it does mean that it should not be done by vpa() and that when it is done, it has to be done carefully. The fancy symbolic rational expressions you see displayed are sometimes internally coded quite differently than you expect.

10 Comments

In the past I have posted code for replacing small symbolic constants. It will take me several minutes to locate (or recreate) the code.
threshold = 1e-10; %change as needed
ZeroSmall = @(x) mapSymType(x, 'vpareal', @(X) piecewise(abs(X)<threshold, 0, X))
ZeroSmall = function_handle with value:
@(x)mapSymType(x,'vpareal',@(X)piecewise(abs(X)<threshold,0,X))
E = sym(pi*10.^(-7:-1:-17).', 'd')
E = 
ZeroSmall(E)
ans = 
EngM
EngM on 11 Feb 2022
Edited: EngM on 11 Feb 2022
Thanks, I appriceate the thorough explanation and I totally agree.. I do have Maple software and Maple goes through the same way of thinking, I remedy this by using the command "fnormal(exp,d). Since Maple is the father of Matlab sym toolbos, it also has vpa and digits, both didn't work for the reasons you just gave.
I tired to run your function, but Matlab threw an error below.. Now, I do have the Symbolic math toolbox, it shows up in the *ver command ->> Symbolic Math Toolbox Version 9.0 (R2021b)
so, not sure what's going on.. uninstalled the toolbox and reinstalled again, no luck. please advise.. thanks a lot.
>>ZeroSmall(kkt)
Unrecognized function or variable 'mupadmexnout'.
Error in sym/mapSymType (line 49)
throw(CaughtMException);
Error in @(x)mapSymType(x,'vpareal',@(X)piecewise(abs(X)<threshold,0,X))
Hi,
I started to believe some of the Sybmolic toolbox functions are not recognized by my matlab for some reason. I do have the symbolic toolbox. For example, when I execute the Matlab Example in the Mathworks Help below https://www.mathworks.com/help/symbolic/matlabfunction.html, I get an error below.
Now, as mentioned above, I do have Maple installed, not sure if that makes a difference. I suppose the toolbox should be standalone even if Maple is installed. Can you please adivce. Thanks.
Unrecognized function or variable 'privResolveArgs'.
Error in sym/symvar (line 30)
Ssym = privResolveArgs(S);
Error in sym/matlabFunction>@(x)symvar(x) (line 220)
vars = cellfun(@(x)symvar(x),funs,'UniformOutput',false);
Error in sym/matlabFunction>getFunVars (line 220)
vars = cellfun(@(x)symvar(x),funs,'UniformOutput',false);
Error in sym/matlabFunction (line 157)
funvars = getFunVars(funs);
When you install Maple onto your system, it looks to see if MATLAB is already installed; if it finds that it is installed, then Maple offers to install the "MATLAB Connector" into MATLAB. The "MATLAB Connector" software is effectively a "toolbox" that gets installed into directories the same kind of way that Mathworks toolboxes would get installed. The installed software gets put onto the MATLAB path. Nothing gets removed from the MATLAB path, just added. The software offers interfaces at the MATLAB level for functions such as syms and vpa and offers a class for tasks such as adding Maple symbolic objects.
However... the Maple functions almost always get added into the MATLAB path before the Mathworks Symbolic Mathematics Toolbox. So while the Mathworks syms function is still on the path, the Maple syms function is found first and is the one used.
If you install Maple first, or install Maple and tell it not to install the "MATLAB Connector" then these hooks do not get installed and you can use the Mathworks toolbox without issue.
What you cannot do is use both at the same time from within MATLAB.
If you ask to uninstall the "MATLAB Connector" then that would normally restore the MATLAB path so that the Mathworks symbolic toolbox became usable again. But if you do not uninstall at all, or do not use the proper uninstall procedures, then you could get parts left around.
If you have both installed, and you use a Mathworks Symbolic Toolbox function that is not present in the Maple interface, there is a risk that you will get a failure instead of just being told the function does not exist.
If you look under the Maple installation directory, there is (if I recall correctly) an Uninstaller specifically for the "MATLAB Connector"
thank you sir..
Hello again,
I just want to add that applying your function to the symbolic experssion increased the execution time significantly.
I thought the digits and vpa is what is supposed to be the solution to increase the speed by reducing the precision. I certainly don't need values like 10e-32! I assumed the vpa functionality should eleiminate such small values to keep the symbolic experession as short as possible, now I am carrying really long experssions full of such small numbers, while in reality these should be fairly short. thanks again.
vpa() adjusts the relative precision. Roughly speaking, it controls the number of digits in scientific notation (and as well, there can be 5 extra "guard" digits in some cases.) So if you have a value that is near 10e-32 then (for example) digits 16 does not mean that values with absolute magnitude less than 10^-16 should be zeroed out: it means that the 10e-32 to 10e-(32+16) would be preserved for that constant .
At the moment nothing comes to mind as to why using my above ZeroSmall function could result in the code taking longer.
... Well, other than the possibility that you had an expression similar to BigConstant*(SmallConstant + variable) in which case the BigConstant*SmallConstant could be important for balancing the equation, and zeroing SmallConstant to get BigConstant*variable might be giving you really the wrong equation to work with.
well, in my case, these are homogeneous transformation matrices, the terms are like 1e-32 * cos(theta) and they will be multiplied with each other or with a position vecotr, which I don't expect to be of a trillion km order.
the number of sym variables in a given matrix can be up to 12 or so, the execution is fairly fast when when less of these small numbers present.
before your code, I was using a function that uses SymToStr(), but after I removed Maple connector, the function no longer available. on the other hand, if I re-install it, the matlabfunction() command no longer be available! which I need to convert these experssions into functions.
If you want to go back to doing text manipulation to zero small coefficients, then use char() or string() . Just be careful because the computing language returned by char() or string() is not exactly MATLAB and is not exactly the internal symbolic language MuPAD. Some of the changes are pretty visible, with phrases like
k in R\Z
showing up. But some of the changes are easily overlooked, such as the order of parameters for the beta() function .
It is not guaranteed that you will be able to use char() followed by str2sym() to get back the original expression.
It is a bit more robust to use matlabFunction() to generate equivalent numeric MATLAB code... provided that your code does not use piecewise(), and provided that you are comfortable with int() being turned into integral()...

Sign in to comment.

More Answers (0)

Products

Release

R2021b

Community Treasure Hunt

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

Start Hunting!