4

I am trying to calculate the time complexity of my fitness function for the genetic algorithm I wrote.

What I did do: I already read a few articles and examples

However non of these were really satisfying, where I could say: Now I know how to apply this on my code.

Let me show you my fitness function, where I guessed a few execution times.

    public static List<double> calculateFitness(List<List<Point3d>> cF, Point3d startpoint)
    {
        List<double> Fitness = new List<double>(); // 1+1
        for (int i = 0; i < cF.Count; i++)  // 1 ; N+1 ; N
        {
            Point3d actual;  // N 
            Point3d next;  // N
            double distance;  // N 
            double totalDistance = startpoint.DistanceTo(cF[i][0]);  // (1+1+1+1)*N
            for (int j = 0; j < cF[i].Count - 1; j++)  // { 1 ; N ; N-1 }*N
            {
                actual = cF[i][j];  // (1+1)*(N-1)
                next = cF[i][j + 1];  // (1+1)*(N-1)

                distance = actual.DistanceTo(next);  // (1+1+1+1)*(N-1)
                totalDistance += distance;  // (1+1)*(N-1)
            }
            totalDistance += cF[i][cF[i].Count - 1].DistanceTo(startpoint);  // (1+1+1+1)*N
            Fitness.Add(totalDistance);  // N
        }
        return Fitness;  // 1
    }

Do you know any links where there are examples, so that I could learn how to calculate the time complexity use-oriented. Or maybe someone can explain it here. For example for this code piece I'm not sure at all: double totalDistance = startpoint.DistanceTo(cF[i][0]); --> (1+1)N ? Or this: actual = cF[i][j]; --> (1+1)NN ?

So in general, the time complexity would be: 1+1+ (1+N+1+N+N+N+N+4N+ N*{ 1+N+N-1+2*(N-1)+2*(N-1)+4*(N-1)+2*(N-1) } +4N+N) = 2 + (2+14N+ N*{12N-10}) = 12N^2 + 4N + 4 = O(N^2)

Community
  • 1
  • 1
Meliss
  • 123
  • 1
  • 8
  • I found this book really good at explaining how to calculate the time complexity of algorithms. https://www.amazon.com/Introduction-Algorithms-3rd-MIT-Press/dp/0262033844 – DaImTo Apr 28 '17 at 13:32
  • It seems like that this book is in the library at our University. I will take a look at it. Thank you :) – Meliss May 03 '17 at 12:10
  • Grab an advanced math book to go along with it you may need it. – DaImTo May 03 '17 at 12:12

1 Answers1

2

Generally when doing Big-O analysis, we ignore constant time operations (i.e. O(1)) and any constant factors. We are just trying to get a sense of how well the algorithm scales with N. What this means in practice is that we are looking for loops and non-constant time operations

With that in mind, I've copied your code below and then annotated certain points of interest.

public static List<double> calculateFitness(List<List<Point3d>> cF, Point3d startpoint)
{
    List<double> Fitness = new List<double>();
    for (int i = 0; i < cF.Count; i++)  // 1.
    {
        Point3d actual;  // 2. 
        Point3d next; 
        double distance;  
        double totalDistance = startpoint.DistanceTo(cF[i][0]);  // 3.
        for (int j = 0; j < cF[i].Count - 1; j++)  // 4.
        {
            actual = cF[i][j];  // 5.
            next = cF[i][j + 1];

            distance = actual.DistanceTo(next);
            totalDistance += distance;
        }
        totalDistance += cF[i][cF[i].Count - 1].DistanceTo(startpoint);
        Fitness.Add(totalDistance); // 6.
    }
    return Fitness;
}
  1. The i loop will execute N times where N is cF.Count. If we were being incredibly formal, we would say that the comparison i < cF.Count takes some constant time c and i++ takes some constant time d. Since they are executed N times, the total time here is cdN. But as I mentioned, Big-O ignores these constant factors and so we say that it is O(N).

  2. These declarations are constant time, O(1).

  3. Indexing into a .NET List is documented as being O(1). I can't find documentation for the DistanceTo method, but I can't imagine it being anything but O(1) because it would be simple math operations.

  4. Here we have another loop that executes N times. If we were being strict about it, we would introduce a second variable here because cF[i].Count isn't necessarily equal to cF.Count. I'm not going to be that strict.

  5. Again, indexing into a list is O(1).

  6. This is actually the tricky one. The Add method is documented as follows:

    If Count is less than Capacity, this method is an O(1) operation. If the capacity needs to be increased to accommodate the new element, this method becomes an O(n) operation, where n is Count.

    • How this is typically implemented, the operation is O(1) most of the time, but is occasionally O(n) where n is the length of the list being added to, Fitness in this case. This is generally referred to as amortized O(1).

So in the end you mainly just have O(1) operations. What there is though is one O(N) loop within another O(N) loop. So the algorithm as a whole is O(N) * O(N) = O(N2).

Community
  • 1
  • 1
DPenner1
  • 9,238
  • 5
  • 30
  • 44
  • Hey, thank you for your time. Your answer really helped a lot. I actually know that when you do a Big-O analysis you have to ignore constant time operations. However I have to write a report about my genetic algorithm and I wanted the analysis to be complete. I can write about the time complexity only when I really understand it. The declarations within the for loop; isn't it executed N times? Because it is executed for every iteration? And would you mind taking another look on how I think the time complexity might be? I'm going to change it in my question block. I would really appreciate it. – Meliss May 03 '17 at 12:28