Hello!
Using r2016a with symbolic math toolbox, but perhaps it is lacking 'piecewise'? Hoping to work with the following function, but have failed with various approaches. Thank you in advance for your suggestions.
Function:
(3*x^2)/100 + 30 if x<22.3607
x^2/100 + 40 if 22.3607<=x<=109.5445
(3*x^2)/400 + 70 if x>109.5445
Option 1) SMT would probably allow:
syms y x
y(x) = piecewise([x<22.3607, (3*x^2)/100 + 30], [22.3607<=x<=109.5445, x^2/100 + 40], [x>109.5445, (3*x^2)/400 + 70)]);
Result:
>> Undefined function or variable 'piecewise'.
Option 2) Create function in .m file:
function y = y(x)
if x<=22.3607;
y = (3*x^2)/100 + 30;
else if 22.3607<x<=109.5445;
y = x^2/100 + 40;
else if 109.5445<x;
y = (3*x^2)/400 + 70;
end
end
end
Result:
>> y_piecewise
Not enough input arguments.
Error in y_piecewise (line 3)
if x<=22.3607;
Option 3) Use heavyside:
y = ['(heaviside(x)-heaviside(x-22.3607))*((3*x^2)/100 + 30) + ' ...
'(heaviside(x-22.3607)-heaviside(x-109.5445))*(x^2/100 + 40) + ' ...
'(heaviside(x-109.5445)-heaviside(x-800))*((3*x^2)/400 + 70)'];
yinv = finverse(y,x)
Result (trying to compute inverse):
>>yinv = 10.0*(x - 40.0)^(1/2)
I would like to be able to input a value for x into this piecewise equation and receive a value for y. I would ideally like to do this for the inverse of the above piecewise function as well. In addition, I would like to compute the diff() and int(), so I believe a symbolic function would be best suited for this. Thoughts? Thank you!!
- Bryan

 Réponse acceptée

Star Strider
Star Strider le 19 Fév 2017

1 vote

This works:
y = @(x) ((3*x.^2)/100 + 30) .* (x<22.3607) + (x.^2/100 + 40) .* ((22.3607<=x) & (x<=109.5445)) + ((3*x.^2)/400 + 70) .* (x>109.5445);
t = linspace(0, 150, 500);
figure(1)
plot(t, y(t))
grid
xlabel('t')
ylabel('y(t)')
title('Original Fincton')
yi = linspace(min(y(t)), max(y(t)), 20); % Interpolate Inverse
ti = interp1(y(t),t, yi, 'linear');
figure(2)
plot(y(t), t) % Plot Inverse
hold on
plot(yi, ti, 'pg', 'MarkerFaceColor','g') % Inverse Interpolated Values
hold off
grid
xlabel('y(t)')
ylabel('t')
title('Inverse Function')
It takes advantage of logical indexing and then just adding pieces of the vector to create a continuous line.
The inverse works with the interp1 function.

Plus de réponses (2)

Walter Roberson
Walter Roberson le 19 Fév 2017
Modifié(e) : Walter Roberson le 19 Fév 2017

1 vote

There is no MATLAB interface to piecewise before R2016b. It is possible to use evalin(symengine) to construct a piecewise object at the mupad level, but you cannot create a function of it.
f = evalin(symengine,'piecewise([x<5,x^2],[x>=5,-x])')
You can subs() into f or you can int(f, x)
Constructing the piecewise by way of a program at the MATLAB level requires some non-obvious steps. It would take me a bit of searching to find where I posted the required helper functions...
Found it.
You would need the helper function that constructs lists, and you would need feval(symengine, 'piecewise',LIST,LIST,...)
whete LIST was constructed by the helper function.

1 commentaire

Walter Roberson
Walter Roberson le 28 Mai 2017
Note: as of R2016b, there is a direct interface to piecewise()

Connectez-vous pour commenter.

Bryan Parthum
Bryan Parthum le 19 Fév 2017

0 votes

Both solutions are a great work-around for what must have been the motivation to develop the piecewise function in SMT r2016b. Thank you both!! I will actually use a mixture of both methods to fit the rest of my needs (not mentioned in the post).
Needless to say, I have submitted to our IT to upgrade our license to r2016b :-)
Thank you!!!
- Bryan

Tags

Community Treasure Hunt

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

Start Hunting!

Translated by