Generating piecewise in r2016a

7 views (last 30 days)
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

Accepted Answer

Star Strider
Star Strider on 19 Feb 2017
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.

More Answers (2)

Walter Roberson
Walter Roberson on 19 Feb 2017
Edited: Walter Roberson on 19 Feb 2017
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 Comment
Walter Roberson
Walter Roberson on 28 May 2017
Note: as of R2016b, there is a direct interface to piecewise()

Sign in to comment.


Bryan Parthum
Bryan Parthum on 19 Feb 2017
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!