Count number of unique symbols in an expression

I'm trying to develop an algorithm that can count how many times each of the syms in a list of parameters (called dimensions shown below) is counted at least once. If any of them in an array containing different combinations or products of the dimensions exist more than once, then it should only register 1 for each them. This part of an algorithm taught in engineering called the Buckingham Pi theorem.
syms M L T Theta d_0
% M: mass
% L: length
% T: time
% Theta: temperature
% d_0: no dimensions, something like an angle or efficiency
% These are the different combinations of dimensions
A = L^2; % maybe an area
V = L/T; % maybe a velocity
D = M/L^3; % maybe a density
% This the array of the combinations
param = {A,V,D};
I want to count how many of the syms M L T and Theta show up in my cell param.
For example starting at the first entry in the cell array.
param{1} = A
L^2
At this step, it should count that L has shown up once, and the others 0 times each.
param{2} = V
L/T
At this step, it counts that L has shown up once, but since it was already counted so I don't want to count it again. It should also count that T has shown up once. So far 1 L, and 1 T.
param{3} = D
M/L^3
Finally, this count that M has shown up once. So far 1 L, 1 T, and 1 M.
Since there are four possible symbols, I want to end the algorithm with this.
j = num; % how many times each of the syms was counted at least once.
If a dimension is not counted, that is fine. I am only interested in counting how many times each of the dimensions in the cell array are counted at least once.
I'm not really sure how to count the dimensions in each combination, but I can handle the combinatorics.
I've tried applying some of this answer, but I've come across these errors when I get to the parameter V = L/T.
Error: Conversion to logical from sym is not possible.
dimen = [M,L,T,Theta]
n = length(param);
u_dimen = zeros(1,length(dimen));
for i=1:n
disp(['Parameter ',num2str(i)])
disp(param(i))
breakinner = false;
for d=1:length(dimen)
disp(dimen(d))
[~,powers] = coeffs(param(i),dimen(d))
exponents = mapSymType(powers, 'power', @(Z) children(Z,2))
if powers(end)==1
exponents(end) = 0
end
exponents
strcmp(class(exponents),'sym')
if exponents>=1 && u_dimen(d)==0
u_dimen(d) = 1;
breakinner = true;
end
clear powers exponents
if breakinner
break
end
end
end
But this doesn't make sense to me since on each run, even when exponents is a number strcmp(class(exponents),'sym') still outputs 1. For example, when dimen(d) = A or L^2, the exponent is a 2 and it gets through the second if statement.

Answers (1)

With limits,
present = cellfun(@(expr), ismember(dimen, symvar(expr)), param, 'UniformOutput', false)
counts = sum(vertcat(present{:}), 1)

6 Comments

limits are that if you have "bound" variables they will not be noticed.
Bound variables: x in the forms
int( expression, x, A, B)
symsum(expression, x, A, B)
symprod(expression, x, A, B)
A variable is bound if you could substitute a different variable in a subexpression without changing the output. A bound variable is like the parameter list in a @() expression
syms x z
f = sin(x) + x
int(f, x, 0, 1)
int(subs(f, x, z), z, 0, 1)
But not
int(f, x)
int(subs(f, x, z), z)
because the indefinite integral is in terms of the variable of integration so it matters which variable name is used
symvar only finds ones that are not bound. bound variables disappear from the result
OK, thanks I will try this by the end of the week and let you know if it is successful.
I'm finally able to get back to this, what is supposed to be represented by @(expr)? Is that meant to be just one of my symbolic variables in my param array?
I won't be taking any integral or derivatives, this is just algebraic combinations.
This is the error message I am getting if I define
expr = param(i)
inside of a for loop.
Error using cellfun
Input #2 expected to be a cell array, was sym instead.
When you have an expression of the form @(VARIABLE) EXPRESSION then that creates an anonymous function. When the function is invoked, then inside EXPRESSION, any plain-text version of VARIABLE will be replaced by the value that is passed in at the corresponding position.
present = cellfun(@(expr), ismember(dimen, symvar(expr)), param, 'UniformOutput', false)
is nearly equivalent to
if exist('expr', 'var')
internal_hidden_variable_have_saved_expr = true;
internal_hidden_variable_saved_expr = expr;
else
internal_hidden_variable_have_saved_expr = false;
end
present = cell(size(param));
for INDEX = 1 : numel(param)
expr = param{INDEX};
present{INDEX} = ismember(dimen, symvar(expr));
end
if internal_hidden_variable_have_saved_expr
expr = internal_hidden_variable_saved_expr;
clear internal_hidden_variable_saved_expr;
else
clear expr
end
clear internal_hidden_variable_have_saved_expr
except internal_hidden_variable_have_saved_expr and internal_hidden_variable_saved_expr would be internal variable names guaranteed not to conflict with any existing variable.
Which is to say that in the form @(VARIABLE) EXPRESSION, that VARIABLE acts as a temporary variable that takes on the value passed in during the execution of EXPRESSION and is afterwards restored to whatever it was.
OK, but MATLAB tells me to remove the comma, and then I get the same error. I am running 2021b.

Sign in to comment.

Categories

Products

Release

R2021b

Community Treasure Hunt

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

Start Hunting!