in below picture I draw a graph base on weight of a controller system against cost function. I want to linearise and divide this curve to for example 5 five intervals. is there any function in mathematica to give me such a thing. I thinking first maybe I can get gradient of function and choose the nearest amount together.
2 Answers
A simple approach. Given a function f
to be plotted, I create a Piecewise
function where I approximate the function with a linear equation for each interval starting at an odd integer. It's quite easy to adapt this solution for any interval setup.
f[x_] := 1/(x);
sol[min_, max_] := First@Solve[{f@min == a min + b, f@max == a max + b}, {a, b}];
linf[t_, {min_, max_, d_}] := Piecewise@Table[
{If[OddQ@i, (a*t + b) /. sol[i, i + d], f@t], i <= t < i + d},
{i, min, max - d, d}];
linf[x, {0, 5, 1}]
Plot[linf[x, {0, 5, 1}], {x, 0, 5},
GridLines -> {Range[0, 5, 1], None},
GridLinesStyle -> Directive[GrayLevel[.3, .3], Dashed],
Mesh -> 4, MeshFunctions -> {#1 &}, MeshShading -> {Dashing[0], Dashed}]
The same with Interpolation
. A Quiet
is needed to prevent the appearance of some error messages related to the fact that Plot
tries to sample the InterpolatingFunction
-s outside their defined intervals as part of its adaptive sampling method.
linIntf[t_, {min_, max_, d_}] := Piecewise@Table[{If[OddQ@i,
Quiet@Interpolation[{{i, f[i]}, {i + d, f[i + d]}},
InterpolationOrder -> 1][t],
f@t
], i <= t < i + d}, {i, min, max-d, d}];
linIntf[x, {0, 5, 1}]
Plot[linIntf[x, {0, 5, 1}], {x, 0, 5},
GridLines -> {Range[0, 5, 1], None},
GridLinesStyle -> Directive[GrayLevel[.3, .3], Dashed], Mesh -> 4,
MeshFunctions -> {#1 &}, MeshShading -> {Dashing[0], Dashed}]
My idea of using Interpolation is this. You have a function defined in an interval [a,b]
f[x_] := 1/(1 + x)
a = 0; b = 6;
Plot[f[x], {x, a, b}, Frame -> True]
Define your n intervals
n = 5;
xrange = Range[a, b, (b - a)/n];
yrange = f[xrange];
And use Interpolation to create your piecewise linear approximation
linf = Interpolation[Transpose[{xrange, yrange}], InterpolationOrder -> 1]
Plot[linf[x], {x, 0, 6}]
You can fit all the steps in a single function that will return an interpolating function
piecewiseLinearize[f_, {x_, a_, b_}, n_] := Module[{xrange, yrange}, xrange = Range[a, b, (b - a)/n]; yrange = (f /. x -> #) & /@ xrange; Interpolation[Transpose[{xrange, yrange}], InterpolationOrder -> 1] ]
Here's how to call it
linf = piecewiseLinearize[f[x], {x, 0, 6}, 5]
Plot[linf[x], {x, 0, 6}]
Interpolation
$\endgroup$