tags:

views:

1422

answers:

6

Hello, I have a little math problem. I would like to have a function with these properties:

  1. for x much bigger than 0: lim f(x) = x
  2. for x much smaller than 0: lim f(x) = 0
  3. and f(0) = 1 (sorry, I had here f(1)=1 which was wrong!)
  4. f(x) should be monotonically increasing

So the function should look somewhat like this:

        ^
        |   /
        |  /
        | /
   ___.-+´
--´-----+------>
        |

The best I got so far is x/(1 + e^(-x)) but then I recognized that it drops below 0 and is not monotonically increasing.

A great help for playing around with these function is GraphFunc Online.

Also, it would be helpful if the function is fast to calculate as I need to execute it very often.

EDIT: I am using this in a program to limit values. I have an optimization algorithm, that uses curve fitting with a Levenberg-Marquardt algorithm. But this algorithm does not allow constraints, and optimizes over the full range of real values. So I need a function like this so that I can add an artificial constraint so that the function is bigger than 0. A simple approach would be to use f(x) = x² but then the function is not monotonically increasing and it has two minimas.

The Levenberg-Marquardt approximates derivatives, so I think it would be best when the function is smooth too. But I am not sure if this is absolutely necessary.

+5  A: 

Except for a discontinuty at 0, x/(1 - e^(-x)) works. So define f(0) to be 1, and you're set.

#define E 2.71828183
double SimpleFunc(double x)
{
   if (x == 0)
      return 1;
   return x / (1 - pow(E, (-x)));
}

Likely faster:

double SimpleFunc2(double x)
{
   if (x < 0)
     return 1/(1 - x);
   return x+1;
}

Both are continuous in the first derivative, but the second one has a jump at 1 in the second derivative)

If you really don't want to do the piece-wise function, try this: (x^2+.1)^.5 / ((1 - e^(-x))^2+.1)^.5

Eclipse
nice! slightly faster would be x/(1 - e^(-x)) of course, due to no neg.
.. and in your "likely faster" variant, on x>0 return x+1 to lessen the discontinuity.
Yep I was going to suggest x/(1 - e^(-x)) as well, but Iraimbilanja beat me to it. :)
grieve
thanks - in my head that was already done.
Eclipse
Your "slightly faster" version isn't monotonically increasing; -26 < -21, but f(-26) = -0.04 is greater than f(-21) = -0.05 (e.g., a more negative value gives a less negative result).
MarkusQ
Also, your slower version doesn't give f(1) = 1, it gives f(1) = -1/(1/e-1)
MarkusQ
f(-26) is (1/27) or 0.037037037, f(-21) is 1/22 or 0.0454545455.
Eclipse
Ahh -= I missed that in the question - I read f(0) should be one.
Eclipse
I believe in your 'SimpleFunc2' function the second return should say 'return 0;' rather than 'return x;', since his definition "for x much smaller than 0: lim f(x) = 0".
Jeff Keslinke
In SimpleFunc, it should be "if (x==0) return 1" as the explanation says.
ketorin
thanks, I am using the second form now. It has the advantage that it is easy to reverse this formula, which I also need
martinus
+3  A: 

f(x) = abs( x/2 ) + x/2

where abs(x) is absolute value of x

This simple function would obviously be fast to compute and meets all four criteria.

Jeremy Rishel
He asked for f(1) to be 1, not f(0) (though his graph, with no scale, may be misleading here).
Jeremy Rishel
It misses #4: f(-10) = 10 > 0 = f(0)
Andrey Fedorov
A: 

I don't know what exactly you're using it for; what's wrong with a piecewise function? If you're going to be executing it a lot, something like this is going to be faster than doing exponents:

f(x) = -1/x, x < -1
f(x) = 1, -1 <= x <= 1
f(x) = x, x > 1

EDIT: Fixed it so it actually works.

Pesto
undefined at x=0 and negative when x<0
Patrick McDonald
@Patrick: D'oh! Thanks.
Pesto
Also for most purposes you usually want smooth transitions from one to another.
Bill K
Rather -1/(x-1) for values below 1.
PhiLho
But is that a requirement? The question really leaves a lot unexplained. At least the revised version is continuous!
Pesto
1/x isn't monotonically increasing
MarkusQ
@PhiLho: That works, too, but this one is continuous, which might be a point in its favor.
Pesto
+1  A: 

Just to give you ideas, this is a solution without the constraint f(1)=1 and not monotonically increasing.

Basically you want to blend between two functions: f1(x) = 0 for x < 0, and f2(x) = x for x > 0. You want to blend that smoothly. A simple step function with a constant limit at -inf and +inf is atan (limits are -pi/2 and +pi/2 respectively).

So combining an atan blend function with f1 and f2, you get:

blend(x) = atan(x)/pi + 0.5 f(x) = (1 - blend(x)) * f1(x) + blend(x) * f2(x)

Which gives:

f(x) = (atan(x)/pi + 0.5) * x

There are probably other blending functions that you can use instead of atan. Also note than with small negative values, f(x) will be negative.

If you want your curve to go through (1,1), you can use the fact that atan(0)=0.

Doub
DOH! You beat me by 40 seconds! :)
Jason S
Actually, if the function has lim f(x)=x, and f(x)=x at x=1, the function has to be piecewise.
Doub
A: 

1/2 * (x + ABS(x))

It is monotonic.

f(1) = 1.

When x is less than zero, f(x) = 0, otherwise it's equal to x.

+6  A: 

Here's a smooth function that satisfies your requirements:

f(x) = (x + sqrt(x^2 + 4)) / 2

For x = 0, you can see that f(x) = 1. For very large positive x, sqrt(x^2 + 4) is approximately x, so f(x) ≈ x. For very large negative x, sqrt(x^2 + 4) is approximately -x, so f(x) ≈ 0.

The first derivative is

f'(x) = 1/2 + 1/2*x/sqrt(x^2 + 4)

For x > 0, x/sqrt(x^2 + 4) > 0, so f'(x) > 0. For x < 0,

0 < x^2/(x^2 + 4) < 1
0 < |x|/sqrt(x^2 + 4) < 1
-1 < x/sqrt(x^2 + 4) < 0
-1/2 < 1/2*x/sqrt(x^2 + 4) < 0
1/2 + 1/2*x/sqrt(x^2 + 4) > 0

Hence, f'(x) > 0 for all x, so f(x) is monotonically increasing as desired.

Adam Rosenfield
Thanks a lot, I use that too. I wish I could accept two answers :)
martinus