Search code examples
c#algorithmmathtimemathematical-optimization

How-to: Find a good mathematical algorithm to distribute measuring points over time?


I'm currently implementing a software that measures certain values over time. The user may choose to measure the value 100 times over a duration of 28 days. (Just to give an example)

Linear distribution is not a problem, but I am currently trying to get a logarithmical distribution of the points over the time span.

The straight-forward implementation would be to iterate over the points and thus I'll need an exponential function. (I've gotten this far!)

My current algorithm (C#) is as follows:

long tRelativeLocation = 0;
double tValue;
double tBase = PhaseTimeSpan.Ticks;
int tLastPointMinute = 0;
TimeSpan tSpan;
for (int i = 0; i < NumberOfPoints; i++)
{
     tValue = Math.Log(i + 1, NumberOfPoints);

     tValue = Math.Pow(tBase, tValue);
     tRelativeLocation = (long)tValue;
     tSpan = new TimeSpan(tRelativeLocation);
     tCurrentPoint = new DefaultMeasuringPointTemplate(tRelativeLocation);
     tPoints.Add(tCurrentPoint);
}

this gives me a rather "good" result for 28 days and 100 points.
The first 11 points are all at 0 seconds,
12th point at 1 sec,
20th at 50 sec,
50th at 390 min,
95th at 28605 mins
99 th at 37697 mins (which makes 43 hours to the last point)

My question is: Does anybody out there have a good idea how to get the first 20-30 points further apart from each other, maybe getting the last 20-30 a bit closer together?

I understand that I will eventually have to add some algorithm that sets the first points apart by at least one minute or so, because I won't be able to get that kind of behaviour into a strictly mathematical algorithm.

Something like this:

if (((int)tSpan.TotalMinutes) <= tLastPointMinute)
{
      tSpan = new TimeSpan((tLastPointMinute +1) * 600000000L);
      tRelativeLocation = tSpan.Ticks;
      tLastPointMinute = (int)tSpan.TotalMinutes;
}

However, I'd like to get a slightly better distribution overall.

Any cool ideas from you math cracks out there would be greatly appreciated!


Solution

  • From a practical point of view, the log function squeezes your time point near the origin already. A power function squeezes them even more. How about simple multiplication?

     tValue = Math.Log(i + 1, NumberOfPoints);
     tValue = tBase * tValue;
    

    Another way to flatten the curve is start farther from the origin.

    for (int i = 0; i < NumberOfPoints; i++)
    {
      tValue = Math.Log(i + 10, NumberOfPoints + 9);
    

    The range of tvalue is still 0 to 1.

    How about this to have a minimum space of 1 second at the beginning?

    double nextTick = 0;
    for (int i = 0; i < NumberOfPoints; i++)
    {
      tValue = Math.Log(i + 1, NumberOfPoints);
    
      tValue = Math.Pow(tBase, tValue);
    
      if (tValue < nextTick) tValue = nextTick;
      nextTick++;