0

I have a function that I want to run with increasing probability each hour until noon then decreasing probability until midnight. I can imagine a normal distribution centered on noon would do it (so the probability of running the function is 100% at noon but very low at midnight), however I cannot convert that into python code.

For example, if the code is executed at 1am it has a very low probability of running. But if the code is executed at noon, it has a 100% probability of running.

This is a completely crude, unpythonic, manual attempt at what I want:

currentHour = 12

if currentHour == 1:
    print('probability = 0')
elif currentHour == 2:
    print('probability = 0')
elif currentHour == 3:
    print('probability = .1')
elif currentHour == 4:
    print('probability = .2')
elif currentHour == 5:
    print('probability = .3')
elif currentHour == 6:
    print('probability = .4')
elif currentHour == 7:
    print('probability = .5')
elif currentHour == 8:
    print('probability = .6')
elif currentHour == 9:
    print('probability = .7')
elif currentHour == 10:
    print('probability = .8')
elif currentHour == 11:
    print('probability = .9')
elif currentHour == 12:
    print('probability = 1')
elif currentHour == 13:
    print('probability = .9')
elif currentHour == 13:
    print('probability = .8')
elif currentHour == 14:
    print('probability = .7')
elif currentHour == 15:
    print('probability = .6')
elif currentHour == 16:
    print('probability = .5')
elif currentHour == 17:
    print('probability = .4')
elif currentHour == 18:
    print('probability = .3')
elif currentHour == 19:
    print('probability = .2')
elif currentHour == 20:
    print('probability = .1')
elif currentHour == 21:
    print('probability = 0')
elif currentHour == 22:
    print('probability = 0')
elif currentHour == 23:
    print('probability = 0')
elif currentHour == 24:
    print('probability = 0')
Anton
  • 4,765
  • 12
  • 36
  • 50
  • 1
    At a bare minimum, use a dictionary. – Morgan Thrapp Oct 07 '16 at 16:14
  • Instead of going up and down by .1, you could use a Box-Mueller transform to make it a normal distribution. See the answer at http://stackoverflow.com/a/75720/509840. Or see the Wikipedia page (with decent code that you can convert) at https://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform – rajah9 Oct 07 '16 at 17:23
  • @rajah9 This formula uses sin(), look at my answer that I gave. – Fusseldieb Oct 07 '16 at 17:30
  • @Fusseldieb Box-Mueller transformation uses both sin and cos. While the area under your curve adds up to 1, it is not a *normal* distribution, which is what the OP asked for. – rajah9 Oct 07 '16 at 19:41

2 Answers2

1

Pure magic. I figured it out. No, just joking. When you asked that question, it immediately reminded me of sinus waves, they go up and then down again - just like your thing you're trying to do.

According to this page:

The graphs of functions defined by y = sin x are called sine waves or sinusoidal waves. [...] This graph repeats every 6.28 units or 2 pi radians. It ranges from -1 to 1.

So I came up with this:

sin((hour/24)*pi)

You can integrate this in python like this:

import math
import time
hour = int(time.strftime("%H"))
probability = math.sin(hour/24.0*math.pi)
print(probability)

Why? Because sin(0*pi) is 0. And sin(0.5*pi) is 1. You want that at 12 hours the probability is the highest, so 1. This value occurs on sin(0.5*pi). On 24 hours, the value will be sin(1*pi), which is 0 again.

Then I converted that value ranging from 0 to 1, to 0 and 24, by dividing the current hour by 24.

Half sine

Fusseldieb
  • 1,324
  • 2
  • 19
  • 44
1

Lots of options. Just make a function that returns a value between 0 and 1 based on the hour. Then, make a random float between 0 and 1. If the float is less than the probability, run the program.

import numpy as np

def prob_sawtooth(hour):
    return 1. - abs((hour - 12.) / 12.)

def prob_sin(hour):
    return np.sin(hour / 24. * np.pi)

def prob_gaussian(hour, stdev=6.):
    gauss = lambda x, m, s: np.exp(-(x-m)**2 / (2*s**2)) / np.sqrt(2*np.pi*s**2)
    return gauss(hour, 12., stdev) / gauss(12., 12., stdev)

test = np.random.rand()
#14:00
if test <= prob_gaussian(14.):
    # run program
    pass
Logan Byers
  • 1,454
  • 12
  • 19