Adjustable Sigmoid Curve (S-Curve) from $(0,0)$ to $ (1,1)$

I put three in a chain: I use the positive domain of the NTS to 'skew' the input, the second is the basic sigmoid, and then I use the positive domain to skew the output. The result is an extremely flexible curve which I tend to use everywhere now. Here is a Desmos sheet, I think it is what you were looking for, although the other answers seem good too. https://www.desmos.com/calculator/tswgrnoosy


I really hate to answer my own question but I believe I found the answer. I tripped across an equation by Game Dev Dino Dini which creates a half normal tunable sigmoid that ranges from $(0,0)$ to $(1,1)$. However the $K$ value is rather wonky in this case. Dino however created another version which he posted via Twitter leading to a half normal tunable sigmoid with a K range from -1 to 1. This equation is...

$$\large \frac{kx-x}{2kx-k-1}=f(x)$$

$$ 0\leq x\leq 1,-1\leq k\leq 1$$

To achieve a S curve in the same range I simply had to scale down the equation and make it piecewise. The lower half then becomes...

$$\large \frac{k*2x-2x}{2k*2x-k-1}*0.5$$ $$or$$ $$\large f(2x)*0.5$$ $$for$$ $$x\leq0.5, -1\leq k \leq 1$$

And then the upper half of the curve is...

$$\large 0.5*\frac{(-k*2(x-0.5))-(2(x-0.5)))}{2*-k*2(x-0.5)-(-k)-1}+0.5$$ $$or$$ $$\large 0.5*f(2(x-0.5))+0.5$$ $$for$$ $$ x>0.5, -1\leq -k \leq 1$$

note the $k$ is negative for the upper half of the curve. Here is an example of the lower half and the upper half. The only issue that remains with this equation is that technically $k = -1,1$ returns $y = 0$, however $k = -0.9...,0.9...$ is close enough. Unfortunately it would appear I cannot adjust my point of inflection to be anything other than $y=x=0.5$ but that was not necessary for the core operation.


3 years late, but I was looking for an answer to the same question & all the responses on here seem overly complicated...

I ended up working it out on my own and got the solution below which is mathematically perfect:

y = 0.5 * (1 + sin((x*pi)-(pi/2)))

Check it out on Wolfram Alpha


Following Micah's comment above I've tried out the cumulative distribution function of the beta distribution, which is available in scipy.special.betainc. It produces nice curves for $a=b\geq 1$. For $a=b<1$ there is a kink, probably due to numerical issues. It might not be the fastest function to compute, but it is readily available.

Plot of the Beta cdf

%matplotlib inline
from scipy.special import betainc
import numpy as np
import math
import matplotlib.pyplot as plt

x = np.linspace(0., 1., 100)
N = 7
for i in range(N):
    k = 0.5 * np.exp(i) / N
    plt.plot(x, betainc(k, k, x))

plt.gca().set_xlim(0,1)
plt.gca().set_ylim(0,1)
plt.show()

  1. Select one extreme "setting" of your curve (eg, the magenta curve in your link).Define your criteria for this shape a bit more carefully, eg: $f(0) = 0$, $f(.5) = .5$, $f(1) = 1$, and function is both continuous and differentiable everywhere. Furthermore, $f(x) > x$ for $0 < x < .5$ and $f(x) > x$ for $.5 < x < 1$.

  2. Divide it in two at what you call the "inflection point" ($x=.5$).

  3. Construct a piecewise smooth function in two pieces (one below $.5$ and one above) with the properties selected in step 1. I recommend using trig functions, but exponential and log functions can be made to work as well. I will call this function $g(x)$. One possibility is given by: $$ .5 sin( 10x/pi ), x\leq.5 \\ -.5 sin( 10x/pi )+1, x>.5 $$ Other options exist, of course.

  4. To achieve other, less extreme, curves in the same family, interpolate linearly, between $g(x)$ and $x$, eg: $f(x) = a * g(x) + (1-a) * x$, where $0 < a < 1$. To other curves in the same family but in the other direction, you will have to extrapolate, but this is simple: $f(x) = a * g(x) + (1-a) * x$, where $-1 < a < 0$. Thus, the complete family is given simply by $f(x) = a * g(x) + (1-a) * x$, where $-1 < a < 1$.