# Continuous non-piecewise equivalent of smoothstep function?

I have a smooth step function given by the piecewise function

smoothstep[x_] := Piecewise[{{0, x <= -(1/2)},
{-20*(x + 1/2)^7 + 70*(x + 1/2)^6 - 84*(x + 1/2)^5 +
35*(x + 1/2)^4, -(1/2) < x < 1/2}, {1, x >= 1/2}}]
Plot[smoothstep[x], {x, -1, 1}]


I'd very much like to find a non-piecewise expression for this - i.e., a single algebraic expression (which I realise will likely contain infinities).

Is it possible to use Mathematica to find such an expression? I tried obtaining an approximation with

interp = InterpolatingPolynomial[{{-10, 0},
{-9, 0, 0}*{-8, 0, 0}, {-7, 0, 0}*{-6, 0, 0}, {-5, 0, 0},
{-4, 0, 0}, {-3, 0, 0}, {-2, 0, 0}, {-1, 0, 0}, {0, 1/2},
{1, 1, 0}, {2, 1, 0}, {3, 1, 0}, {4, 1, 0}, {5, 1, 0},
{6, 1, 0}, {7, 1, 0}, {8, 1, 0}, {9, 1, 0}, {10, 1, 0}}, x]


but it produces a nonsense-plot:

Suggestions? Or can it simply not be done?

UPDATE

Both @Michael and @Thies provide excellent answers below. I have ticked @Michael's because it is more comprehensive, but both are correct and useful.

• Looks like a logistic – corey979 Dec 21 '18 at 13:19
• the difference is that logistic curves tend towards 0 and 1 rather than actually reaching those values at a specified value of x - hence the fact that the smooth step is piecewise... – Richard Burke-Ward Dec 21 '18 at 14:07
• How smooth do you want your curve to be? How many derivatives should be continuous? Can you have a curve that is not piecewise but is actually equal to 0 and 1 away from the step? – Hugh Dec 21 '18 at 14:24
• Ideally infinitely differentiable, and about as smooth as the piecewisesmoothstep function I gave in the OP. It doesn't have to be that curve, though... And I don't know the answer to whether it's possible. That's the main reason I'm asking the question! Thanks for your thought and input. – Richard Burke-Ward Dec 21 '18 at 15:00
• I think you want a bump function, a function with compact support that is infinitely differentiable. Even more suiting seems to be a smooth function or Mollified version of a unit step. The article about smooth functions also has an example of a smooth unit step. I can write an answer if you need more details. – Thies Heidecke Dec 21 '18 at 15:06

Here's an "algebraic expression" using the same sort of smooth ($$C^\infty$$) transition function as @Thies's:

Plot[
1/4 (2 + (-2 + 4 x)/
Sqrt[(1 - 2 x)^2] + ((1 +
Sqrt[(-1 + 2 x)^2]/(1 - 2 x)) (1 + (1 + 2 x)/
Sqrt[(1 + 2 x)^2]))/(1 + E^((8 x)/(-1 + 4 x^2)))),
{x, -1, 1}]


Like @Thies's, it's not Mathematica-lly differentiable at the points where the function transitions to a constant, even though it is mathematically infinitely differentiable there. This is due to the way derivatives of Piecewise[] are handled in @Thies's and because mine has a divide-by-zero error.

Addendum. The only way I've figured out how to get a function that Mathematica will yield a symbolic derivative at the transition points is by overriding the differentiation operator. To make it numerically and symbolically efficient requires some work:

ClearAll[smoothstep,
ss0, dss, idss,(* internal aux fns (smoothstep, derivative, internal derivative *)
smoothstepExpand];
Block[{x},   (* because x is evaluated in some definitions *)
ss0[x_] := 1/(1 + Exp[2/(2 x + 1) - 2/(1 - 2 x)]);  (* base expression *)
dss[0, x_] = Piecewise[{  (* complete base function *)
{ss0[x], -1/2 < x < 1/2},
{1, x >= 1/2}}];
smoothstep[x_?NumericQ] = dss[0, x];  (* function, limited to eval on numerical input *)
(* idss[n,x] is the general n-th derivative, which has the form of an
inactivated Sum[] in terms of a DifferenceRoot[];
idss[] is numerically unstable near x==1/2, but when simplified, behaves better;
hence in dss[] below, which calls idss[], one sees Simplify@Activate@idss[n,y] *)
idss[n_, x_] = Piecewise[{{D[ss0[x], {x, n}], -1/2 < x < 1/2}}];
dss[n_, x_] := Block[{y},  (* called internally for a specific positive integer n *)
dss[n, y_] = Simplify@Activate@idss[n, y]; (* memoize simplified symbolic derivative *)
dss[n, x]];
Derivative[n_Integer?Positive][smoothstep][x_?NumericQ] :=
dss[n, x];  (* evaluate derivative at numeric input *)
smoothstepExpand[expr_] :=
expr /. {  (* expand smoothstep[], smoothstep'[] etc. into Piecewise expressions *)
HoldPattern[smoothstep[x_]] :> dss[0, x],
HoldPattern[Derivative[n_Integer?Positive][smoothstep][x0_]] :>
dss[n, x0]}
]

Plot[
{smoothstep[x], smoothstep'[x]},
{x, -1, 1}]


You want a smooth function or bump function, a function with compact support which is infinitely differentiable. An example for a smooth unit step given in the Wikipedia article is

f[x_] := Boole[x > 0] Exp[-1/x]
g[x_] := f[x] / (f[x] + f[1-x])

Plot[g[x], {x, -0.1, 1.1}]


An equivalent definition is

g[x]//PiecewiseExpand//FullSimplify

Piecewise[{
{0, x <= 0},
{1/(1+Exp[1/x - 1/(1-x)]), 0 < x < 1},
{1, True}}
]


Try Tanh[x]

Plot[{smoothstep[x], (1 + Tanh[x 5])/2}, {x, -1, 1}]


• Thanks @Ulrich but this is asymptotic again... – Richard Burke-Ward Dec 21 '18 at 22:38

I don't know know if you like this any better, but I'm not sure what you have against Piecewise. You can convert to UnitStep with:

smoothstep[x_] =  SimplifyPWToUnitStep@ Piecewise[{{0,
x <= -(1/2)}, {-20*(x + 1/2)^7 + 70*(x + 1/2)^6 -
84*(x + 1/2)^5 + 35*(x + 1/2)^4, -(1/2) < x < 1/2}, {1,  x >= 1/2}}]
(*1/16 (-(320 x^7) + 336 x^5 - 140 x^3 + 35 x + 8) (1 -  UnitStep[-x - 1/2]) (1 - UnitStep[x - 1/2]) + UnitStep[x - 1/2]*)
`

The plots of the function and its derivatives look the same as original.

• I'd like to mark more than one answer as 'correct' - how do I do that? – Richard Burke-Ward Dec 27 '18 at 10:39
• I don't think that that is possible. – Bill Watts Dec 27 '18 at 20:33