How to use solve() with max()

5 views (last 30 days)
newbie9
newbie9 on 24 Feb 2018
Commented: newbie9 on 26 Feb 2018
Hello, I am trying to solve() the equation pictured for "A" (Actually, A = L*H, and I am trying to solve for L. Known: M, H, beta, const. Unknown: L)
I have tried the following code:
syms L W M
M = 6; H = 15;
eqn = [log10(L*H)+(2/3)*log10(max(1,sqrt(L*H/H^2))/((1+max(1,L*H/(H^2*7.4)))/2))+3.98 == M];
vars = [L H M];
[solv, solu] = solve(eqns, vars)
But I receive an error: "Error using symengine Input arguments must be convertible to floating-point numbers."
I think the error is from the max() terms.
I tried a test re-writing as piecewise()
syms L W M
M = 6; W = 15;
eqn = [log10(L*W)+(2/3)*log10(piecewise(sqrt(L*W/W^2) > 1, sqrt(L*W/W^2), 1)/((piecewise(L*W/(W^2*7.4) >1, L*W/(W^2*7.4), 1))/2))+3.98 == M];
vars = [L W M];
[solv, solu] = solve(eqn, vars)
And receive the following error: "Error using sym.getEqnsVars>checkVariables (line 92)Second argument must be a vector of symbolic variables."
I'm sure I'm missing something that should be obvious, but any help would be appreciated--thx!

Answers (1)

Walter Roberson
Walter Roberson on 24 Feb 2018
piecewise is the correct approach.
In the second case you are asking to solve a single equation in the single variable L with respect to the variable L and the constants 15 and 6. You cannot solve with respect to numeric constants. When you assign a numeric value to a variable it loses its previous identity as being symbolic. If you had not assigned constants to those variables then you would not have gotten that error, but you would still be trying to solve a single equation with respect to 3 variables.
  4 Comments
Walter Roberson
Walter Roberson on 26 Feb 2018
Revised code for the case where I also declare M and W to be real:
syms L
syms M W nonnegative real
Q = @(v)sym(v,'r');
eqn = [log10(L*W)+(Q(2)/3)*log10(piecewise(sqrt(L*W/W^2) > 1, sqrt(L*W/W^2), 1)/((piecewise(L*W/(W^2*Q(7.4)) >1, L*W/(W^2*Q(7.4)), 1))/Q(2)))+Q(3.98) == M];
sol = solve(eqn, L, 'returnconditions', true);
%now try specific values
solL = subs(sol.L, [M, W], [6, 15]);
solcond = subs(sol.conditions, [M,W], [6,15]);
ncond = length(solcond);
param = sol.parameters;
solz = cell(ncond,1);
if isempty(param)
valid_z_mask = simplify(solcond);
valid_L = solL(valid_z_mask) %in this case you can be sure it will be a vector
else
for K = 1 : ncond
thiscond = solcond(K);
solz{K} = solve(thiscond, param);
end
valid_z_mask = ~cellfun(@isempty, solz);
valid_L = arrayfun(@(L,Zcell) subs(L, Zcell{1}), solL(valid_z_mask), solz(valid_z_mask), 'uniform', 0) %in this case the number of results for each case is uncertain
end
There are two paths here.
Without the 'real', the original solve() returns a vector of values, each with an associated condition, and with one of the values parameterized by an extra variable whose value needs to be determined later. The general flow for this is to solve for each possible value of the extra variable and substitute that value back into the solutions for L. But for any particular M and W value, some of the potential values might be ruled out, giving an empty solution, so you need to do some filtering on the solution set of L.
With the 'real' in place, the original solve() returns a vector of values, each with an associated condition, but already has enough information that no extra variables are needed. In this case with no auxillary variable, when you substitute particular numeric values into the conditions, you get a vector of true and false values as to whether the condition is fulfilled, and you can use that to filter the list of solutions for L.
newbie9
newbie9 on 26 Feb 2018
Thank you so much Walter! I appreciate your time and clear explanation.

Sign in to comment.

Tags

Community Treasure Hunt

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

Start Hunting!