Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked
 
PerlMonks  

[OT] Normalizing the return result of an exponential formula

by clinton (Priest)
on Apr 14, 2011 at 15:45 UTC ( [id://899463]=perlquestion: print w/replies, xml ) Need Help??

clinton has asked for the wisdom of the Perl Monks concerning the following question:

I'm trying to come up with a formula that I can use to represent distance from a central point, and will return a boost value in a range, eg 0..10.

This formula can accept two (or maybe 3) variables:

  1. importance: this controls the upper limit of the range, eg 0..10, 0..100
  2. radius: ie any distance within this inner radius should be pretty much as important as any other point within this radius
  3. dropoff: (optional) how quickly the boost should drop off as distance increases

My basic formula is:

boost = importance / ((radius + distance) ** dropoff)
For instance, an importance of 100, a dropoff of 0.5 and a radius of 0 gives me a curve like:
16 : @@@@@@@@@@@@@@@@@@@@@@@@@ 32 : @@@@@@@@@@@@@@@@@ 64 : @@@@@@@@@@@@ 128 : @@@@@@@@ 256 : @@@@@@ 512 : @@@@ 1024 : @@@ 2048 : @@ 4096 : @ 8192 : @
But with a radius of 1000, I get a much smaller range:
16 : @@@ 32 : @@@ 64 : @@@ 128 : @@ 256 : @@ 512 : @@ 1024 : @@ 2048 : @ 4096 : @ 8192 : @

I would like to change the formula to make the upper limit of the range dependent only on importance and not on radius. For the life of me I can't figure out how to do that.

PS: distance can be considered to have an upper limit of, eg, 10,000km if that helps

PPS: As an optional extra, it would be nice to be able to configure the rate of dropoff without affecting the upper limit of the range, but I can live without it

Replies are listed 'Best First'.
Re: [OT] Normalizing the return result of an exponential formula
by kennethk (Abbot) on Apr 14, 2011 at 18:00 UTC
    Based on your post and discussion with BrowserUk, my first thought is a Gaussian - see Normal_distribution. The functional form gives you a width parameter and the normalization is known, so it will satisfy your importance and radius requirements. You could probably implement your boost parameter by modifying the exponent on x. Perhaps something like:
    #!/usr/bin/perl -w use warnings; use strict; sub boost { my ($x, $importance, $radius, $drop) = @_; return $importance * exp( -($x/$radius)**$drop ); } my $imp = 1000; my $rad = 100; my $drop = 1; for (map 2**$_, 1..15) { my $boost = boost($_, $imp, $rad, $drop); my $bar = "@" x ($boost/$imp*50); printf "%6d %s %.1f\n", $_, $bar, $boost; } __END__ 2 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 980.2 4 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 960.8 8 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 923.1 16 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 852.1 32 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 726.1 64 @@@@@@@@@@@@@@@@@@@@@@@@@@ 527.3 128 @@@@@@@@@@@@@ 278.0 256 @@@ 77.3 512 6.0 1024 0.0 2048 0.0 4096 0.0 8192 0.0 16384 0.0 32768 0.0

    Update: Fixed typo in call order.

      kennethk that looks like just the ticket! Many thanks
Re: [OT] Normalizing the return result of an exponential formula
by Eliya (Vicar) on Apr 14, 2011 at 17:29 UTC

    Maybe I'm misunderstanding, but why not simply return the max value when the distance falls within the radius, and apply the dropoff to what falls outside?  In code:

    sub boost { my ($dist, $imp, $rad, $drop) = @_; if ($dist <= $rad) { return $imp; } else { return $imp / ($dist - $rad + 1) ** $drop; } } my $imp = 1000; my $rad = 125; my $drop = 0.5; for (map 2**$_, 4..13) { my $boost = boost($_, $imp, $rad, $drop); my $bar = "@" x ($boost/($imp*0.02)); printf "%6d %s %.1f\n", $_, $bar, $boost; } __END__ 16 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 1000.0 32 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 1000.0 64 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 1000.0 128 @@@@@@@@@@@@@@@@@@@@@@@@@@@@ 577.4 256 @@@@ 87.4 512 @@ 50.8 1024 @ 33.4 2048 @ 22.8 4096 15.9 8192 11.1
      Hi Eliya

      That's kinda what I want, I think.

      It also handles the case where the distance is 1cm, making the boost way too large. Although, I probably want the decline for distances greater than the radius to be less steep, ie the remaining range should be stretched.

      Still experimenting, but I think that by combining what you suggest with something like in Re: [OT] Normalizing the return result of an exponential formula, I might get a reasonable result.

      Rereading your code, I see you handle the decline, taking the radius into account. That could be it! Thanks

Re: [OT] Normalizing the return result of an exponential formula
by BrowserUk (Patriarch) on Apr 14, 2011 at 16:38 UTC
    I would like to change the formula to make the upper limit of the range dependent only on importance and not on radius.

    Why not just omit the radius from the equation?

    That way, the 'boost' become dependant upon just the distance from the perimeter of the circle regardless of the circles size:

    sub x{ my( $i, $r, $d, $o ) = @_; return $i / $d**$o; } print x( 100, 0, $_, 0.5 ) for map 2**$_, 4..13;; 25 17.6776695296637 12.5 8.83883476483184 6.25 4.41941738241592 3.125 2.20970869120796 1.5625 1.10485434560398 print x( 100, 1000, $_, 0.5 ) for map 2**$_, 4..13;; 25 17.6776695296637 12.5 8.83883476483184 6.25 4.41941738241592 3.125 2.20970869120796 1.5625 1.10485434560398

    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.

      What I was trying to achieve with radius was to give the user the ability to say: "anything within this circle is really important", where that circle might be a country, or a province. So the curve might look like:

      16 : @@@@@@@@@@@@@@@@@@@@@@@@@ - 32 : @@@@@@@@@@@@@@@@@@@@@@@@ | inside radius 64 : @@@@@@@@@@@@@@@@@@@@@@ - 128 : @@@@@@@@@@@@@@ 256 : @@@@@@@@@@ 512 : @@@@@@ 1024 : @@@ 2048 : @@ 4096 : @ 8192 : @

        Then I misunderstand what you meant by "2. radius: ie any distance within this inner radius should be pretty much as important as any other point within this radius"

        To me that reads as, everything inside the circle is equally important, but as the distance outside that circle increases, the importance falls off exponentially. This was reinforced by your adding the distance to the radius in your formula.

        As that does not appear to be the case, and as you new diagram does nothing to explain the relationship between 'radius' and 'distance', I think you are going to have to explain the relationships between the 4 input variables much more clearly?

        For at least me. I'm sometimes quite good at reading between the lines, but with your latest information I cannot reconcile your formula, terminology, and stated goals.Ie.

        Is 'distance' measured inside the circle? From the centre toward the edge? Or from the edge toward the centre?

        Is 'boost' an exponential decline in 'importance' over 'distance'? As suggested by the term 'dropoff'. (It is a strange name for a decline in anything?)


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
Re: [OT] Normalizing the return result of an exponential formula
by clinton (Priest) on Apr 14, 2011 at 16:34 UTC
    I suppose I could do something like:
    my $max = 10_000; $distance -= $radius; $distance = 0 if $distance < 0; $distance *= $max/($max-$radius)
    then apply the formula to the new "stretched" distance.

    Any more elegant way of handling it? (especially one that incorporates dropoff?)

Re: [OT] Normalizing the return result of an exponential formula
by anonymized user 468275 (Curate) on Apr 18, 2011 at 14:43 UTC
    What I am missing:

    - how the y-value should tend to a limit as the distance approaches the radius (quadratically? hyperbolically? exponentially? linearly?.

    - Should the function be continuous or discontinuous at the exact radius point.

    - What should be the slope of the curve at that point? (or the slope as it tends to it on either side if the function should be discontinuous)

    - How should the y-value decay to 0 as distance tends to infinity (same options as my first question.

    Update: I'll rephrase this all in plainer English:-

    If you were to draw a 2-D graph of this with x is distance on the horizontal axis and y is boost on the vertical axis, and that graph represents a function f, so that y=f(x), there will be a starting value for boost where distance is 0 let's say Z = f(0). From your description, this should decay firstly to f(R), so f(R) < Z. After that it drops more rapidly towards zero. So to describe an example formula for f(x), a mathematician needs to know the shape of the curve before and after the point x=R and whether the point at x=R is smooth or a corner or whether it jumps to a different value at that point (otherwise known as a point of discontinuity). Given this information it then possible to translate the function into Perl.

    One world, one people

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://899463]
Approved by eff_i_g
Front-paged by eff_i_g
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others romping around the Monastery: (9)
As of 2024-04-18 11:09 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found