Traveling Salesman Problem using Genetic Algorithm
Last Updated :
30 Apr, 2024
AuPrerequisites: Genetic Algorithm, Travelling Salesman Problem
In this article, a genetic algorithm is proposed to solve the travelling salesman problem.Â
Genetic algorithms are heuristic search algorithms inspired by the process that supports the evolution of life. The algorithm is designed to replicate the natural selection process to carry generation, i.e. survival of the fittest of beings. Standard genetic algorithms are divided into five phases which are:Â
Â
- Creating initial population.
- Calculating fitness.
- Selecting the best genes.
- Crossing over.
- Mutating to introduce variations.
These algorithms can be implemented to find a solution to the optimization problems of various types. One such problem is the Traveling Salesman Problem. The problem says that a salesman is given a set of cities, he has to find the shortest route to as to visit each city exactly once and return to the starting city.Â
Approach: In the following implementation, cities are taken as genes, string generated using these characters is called a chromosome, while a fitness score which is equal to the path length of all the cities mentioned, is used to target a population.
Fitness Score is defined as the length of the path described by the gene. Lesser the path length fitter is the gene. The fittest of all the genes in the gene pool survive the population test and move to the next iteration. The number of iterations depends upon the value of a cooling variable. The value of the cooling variable keeps on decreasing with each iteration and reaches a threshold after a certain number of iterations.
Algorithm:Â
Â
1. Initialize the population randomly.
2. Determine the fitness of the chromosome.
3. Until done repeat:
1. Select parents.
2. Perform crossover and mutation.
3. Calculate the fitness of the new population.
4. Append it to the gene pool.
Â
Pseudo-codeÂ
Â
Initialize procedure GA{
Set cooling parameter = 0;
Evaluate population P(t);
While( Not Done ){
Parents(t) = Select_Parents(P(t));
Offspring(t) = Procreate(P(t));
p(t+1) = Select_Survivors(P(t), Offspring(t));
t = t + 1;
}
}
How the mutation works?
Suppose there are 5 cities: 0, 1, 2, 3, 4. The salesman is in city 0 and he has to find the shortest route to travel through all the cities back to the city 0. A chromosome representing the path chosen can be represented as:Â
Â

This chromosome undergoes mutation. During mutation, the position of two cities in the chromosome is swapped to form a new configuration, except the first and the last cell, as they represent the start and endpoint.Â
Â

Original chromosome had a path length equal to INT_MAX, according to the input defined below, since the path between city 1 and city 4 didn’t exist. After mutation, the new child formed has a path length equal to 21, which is a much-optimized answer than the original assumption. This is how the genetic algorithm optimizes solutions to hard problems.
Â
Below is the implementation of the above approach:
Â
C++
// C++ implementation of the above approach
#include <bits/stdc++.h>
#include <limits.h>
using namespace std;
// Number of cities in TSP
#define V 5
// Names of the cities
#define GENES ABCDE
// Starting Node Value
#define START 0
// Initial population size for the algorithm
#define POP_SIZE 10
// Structure of a GNOME
// string defines the path traversed
// by the salesman while the fitness value
// of the path is stored in an integer
struct individual {
string gnome;
int fitness;
};
// Function to return a random number
// from start and end
int rand_num(int start, int end)
{
int r = end - start;
int rnum = start + rand() % r;
return rnum;
}
// Function to check if the character
// has already occurred in the string
bool repeat(string s, char ch)
{
for (int i = 0; i < s.size(); i++) {
if (s[i] == ch)
return true;
}
return false;
}
// Function to return a mutated GNOME
// Mutated GNOME is a string
// with a random interchange
// of two genes to create variation in species
string mutatedGene(string gnome)
{
while (true) {
int r = rand_num(1, V);
int r1 = rand_num(1, V);
if (r1 != r) {
char temp = gnome[r];
gnome[r] = gnome[r1];
gnome[r1] = temp;
break;
}
}
return gnome;
}
// Function to return a valid GNOME string
// required to create the population
string create_gnome()
{
string gnome = "0";
while (true) {
if (gnome.size() == V) {
gnome += gnome[0];
break;
}
int temp = rand_num(1, V);
if (!repeat(gnome, (char)(temp + 48)))
gnome += (char)(temp + 48);
}
return gnome;
}
// Function to return the fitness value of a gnome.
// The fitness value is the path length
// of the path represented by the GNOME.
int cal_fitness(string gnome)
{
int map[V][V] = { { 0, 2, INT_MAX, 12, 5 },
{ 2, 0, 4, 8, INT_MAX },
{ INT_MAX, 4, 0, 3, 3 },
{ 12, 8, 3, 0, 10 },
{ 5, INT_MAX, 3, 10, 0 } };
int f = 0;
for (int i = 0; i < gnome.size() - 1; i++) {
if (map[gnome[i] - 48][gnome[i + 1] - 48] == INT_MAX)
return INT_MAX;
f += map[gnome[i] - 48][gnome[i + 1] - 48];
}
return f;
}
// Function to return the updated value
// of the cooling element.
int cooldown(int temp)
{
return (90 * temp) / 100;
}
// Comparator for GNOME struct.
bool lessthan(struct individual t1,
struct individual t2)
{
return t1.fitness < t2.fitness;
}
// Utility function for TSP problem.
void TSPUtil(int map[V][V])
{
// Generation Number
int gen = 1;
// Number of Gene Iterations
int gen_thres = 5;
vector<struct individual> population;
struct individual temp;
// Populating the GNOME pool.
for (int i = 0; i < POP_SIZE; i++) {
temp.gnome = create_gnome();
temp.fitness = cal_fitness(temp.gnome);
population.push_back(temp);
}
cout << "\nInitial population: " << endl
<< "GNOME FITNESS VALUE\n";
for (int i = 0; i < POP_SIZE; i++)
cout << population[i].gnome << " "
<< population[i].fitness << endl;
cout << "\n";
bool found = false;
int temperature = 10000;
// Iteration to perform
// population crossing and gene mutation.
while (temperature > 1000 && gen <= gen_thres) {
sort(population.begin(), population.end(), lessthan);
cout << "\nCurrent temp: " << temperature << "\n";
vector<struct individual> new_population;
for (int i = 0; i < POP_SIZE; i++) {
struct individual p1 = population[i];
while (true) {
string new_g = mutatedGene(p1.gnome);
struct individual new_gnome;
new_gnome.gnome = new_g;
new_gnome.fitness = cal_fitness(new_gnome.gnome);
if (new_gnome.fitness <= population[i].fitness) {
new_population.push_back(new_gnome);
break;
}
else {
// Accepting the rejected children at
// a possible probability above threshold.
float prob = pow(2.7,
-1 * ((float)(new_gnome.fitness
- population[i].fitness)
/ temperature));
if (prob > 0.5) {
new_population.push_back(new_gnome);
break;
}
}
}
}
temperature = cooldown(temperature);
population = new_population;
cout << "Generation " << gen << " \n";
cout << "GNOME FITNESS VALUE\n";
for (int i = 0; i < POP_SIZE; i++)
cout << population[i].gnome << " "
<< population[i].fitness << endl;
gen++;
}
}
int main()
{
int map[V][V] = { { 0, 2, INT_MAX, 12, 5 },
{ 2, 0, 4, 8, INT_MAX },
{ INT_MAX, 4, 0, 3, 3 },
{ 12, 8, 3, 0, 10 },
{ 5, INT_MAX, 3, 10, 0 } };
TSPUtil(map);
}
Java
import java.util.*;
public class TSP {
// Constants and global variables
static int V = 5;
static int INT_MAX = 2147483647;
static int POP_SIZE = 10;
static int gen_thres = 5;
static double temperature = 10000;
// Structure of a GNOME
static class Individual {
String gnome;
int fitness;
public Individual(String gnome, int fitness) {
this.gnome = gnome;
this.fitness = fitness;
}
}
// Function to return a random number from start and end
static int rand_num(int start, int end) {
return (int) (Math.random() * (end - start)) + start;
}
// Function to check if the character has already occurred in the string
static boolean repeat(String s, char ch) {
return s.indexOf(ch) >= 0;
}
// Function to return a mutated GNOME
static String mutatedGene(String gnome) {
while (true) {
int r = rand_num(1, V);
int r1 = rand_num(1, V);
if (r1 != r) {
char[] gnomeArr = gnome.toCharArray();
char temp = gnomeArr[r];
gnomeArr[r] = gnomeArr[r1];
gnomeArr[r1] = temp;
return new String(gnomeArr);
}
}
}
// Function to return a valid GNOME string
static String create_gnome() {
String gnome = "0";
while (true) {
if (gnome.length() == V) {
gnome += gnome.charAt(0);
break;
}
int temp = rand_num(1, V);
if (!repeat(gnome, (char) (temp + 48))) {
gnome += (char) (temp + 48);
}
}
return gnome;
}
// Function to return the fitness value of a gnome
static int cal_fitness(String gnome) {
int[][] mp = {
{0, 2, INT_MAX, 12, 5},
{2, 0, 4, 8, INT_MAX},
{INT_MAX, 4, 0, 3, 3},
{12, 8, 3, 0, 10},
{5, INT_MAX, 3, 10, 0},
};
int f = 0;
for (int i = 0; i < gnome.length() - 1; i++) {
if (mp[gnome.charAt(i) - 48][gnome.charAt(i + 1) - 48] == INT_MAX) {
return INT_MAX;
}
f += mp[gnome.charAt(i) - 48][gnome.charAt(i + 1) - 48];
}
return f;
}
// Function to return the updated value of the cooling element
static double cooldown(double temp) {
return (90 * temp) / 100;
}
public static void main(String[] args) {
// Initial population
List<Individual> population = new ArrayList<>();
for (int i = 0; i < POP_SIZE; i++) {
String gnome = create_gnome();
int fitness = cal_fitness(gnome);
population.add(new Individual(gnome, fitness));
}
// Iteration to perform population crossing and gene mutation
int gen = 1;
while (temperature > 1000 && gen <= gen_thres) {
Collections.sort(population, Comparator.comparingInt(a -> a.fitness));
List<Individual> new_population = new ArrayList<>();
for (Individual p1 : population) {
while (true) {
String new_g = mutatedGene(p1.gnome);
int new_fitness = cal_fitness(new_g);
Individual new_gnome = new Individual(new_g, new_fitness);
if (new_gnome.fitness <= p1.fitness) {
new_population.add(new_gnome);
break;
} else {
double prob = Math.pow(2.7, -1 * ((double) (new_gnome.fitness - p1.fitness) / temperature));
if (prob > 0.5) {
new_population.add(new_gnome);
break;
}
}
}
}
temperature = cooldown(temperature);
population = new_population;
System.out.println("Generation " + gen);
for (Individual ind : population) {
System.out.println(ind.gnome + " " + ind.fitness);
}
gen++;
}
}
}
Python3
# Python3 implementation of the above approach
from random import randint
INT_MAX = 2147483647
# Number of cities in TSP
V = 5
# Names of the cities
GENES = "ABCDE"
# Starting Node Value
START = 0
# Initial population size for the algorithm
POP_SIZE = 10
# Structure of a GNOME
# defines the path traversed
# by the salesman while the fitness value
# of the path is stored in an integer
class individual:
def __init__(self) -> None:
self.gnome = ""
self.fitness = 0
def __lt__(self, other):
return self.fitness < other.fitness
def __gt__(self, other):
return self.fitness > other.fitness
# Function to return a random number
# from start and end
def rand_num(start, end):
return randint(start, end-1)
# Function to check if the character
# has already occurred in the string
def repeat(s, ch):
for i in range(len(s)):
if s[i] == ch:
return True
return False
# Function to return a mutated GNOME
# Mutated GNOME is a string
# with a random interchange
# of two genes to create variation in species
def mutatedGene(gnome):
gnome = list(gnome)
while True:
r = rand_num(1, V)
r1 = rand_num(1, V)
if r1 != r:
temp = gnome[r]
gnome[r] = gnome[r1]
gnome[r1] = temp
break
return ''.join(gnome)
# Function to return a valid GNOME string
# required to create the population
def create_gnome():
gnome = "0"
while True:
if len(gnome) == V:
gnome += gnome[0]
break
temp = rand_num(1, V)
if not repeat(gnome, chr(temp + 48)):
gnome += chr(temp + 48)
return gnome
# Function to return the fitness value of a gnome.
# The fitness value is the path length
# of the path represented by the GNOME.
def cal_fitness(gnome):
mp = [
[0, 2, INT_MAX, 12, 5],
[2, 0, 4, 8, INT_MAX],
[INT_MAX, 4, 0, 3, 3],
[12, 8, 3, 0, 10],
[5, INT_MAX, 3, 10, 0],
]
f = 0
for i in range(len(gnome) - 1):
if mp[ord(gnome[i]) - 48][ord(gnome[i + 1]) - 48] == INT_MAX:
return INT_MAX
f += mp[ord(gnome[i]) - 48][ord(gnome[i + 1]) - 48]
return f
# Function to return the updated value
# of the cooling element.
def cooldown(temp):
return (90 * temp) / 100
# Comparator for GNOME struct.
# def lessthan(individual t1,
# individual t2)
# :
# return t1.fitness < t2.fitness
# Utility function for TSP problem.
def TSPUtil(mp):
# Generation Number
gen = 1
# Number of Gene Iterations
gen_thres = 5
population = []
temp = individual()
# Populating the GNOME pool.
for i in range(POP_SIZE):
temp.gnome = create_gnome()
temp.fitness = cal_fitness(temp.gnome)
population.append(temp)
print("\nInitial population: \nGNOME FITNESS VALUE\n")
for i in range(POP_SIZE):
print(population[i].gnome, population[i].fitness)
print()
found = False
temperature = 10000
# Iteration to perform
# population crossing and gene mutation.
while temperature > 1000 and gen <= gen_thres:
population.sort()
print("\nCurrent temp: ", temperature)
new_population = []
for i in range(POP_SIZE):
p1 = population[i]
while True:
new_g = mutatedGene(p1.gnome)
new_gnome = individual()
new_gnome.gnome = new_g
new_gnome.fitness = cal_fitness(new_gnome.gnome)
if new_gnome.fitness <= population[i].fitness:
new_population.append(new_gnome)
break
else:
# Accepting the rejected children at
# a possible probability above threshold.
prob = pow(
2.7,
-1
* (
(float)(new_gnome.fitness - population[i].fitness)
/ temperature
),
)
if prob > 0.5:
new_population.append(new_gnome)
break
temperature = cooldown(temperature)
population = new_population
print("Generation", gen)
print("GNOME FITNESS VALUE")
for i in range(POP_SIZE):
print(population[i].gnome, population[i].fitness)
gen += 1
if __name__ == "__main__":
mp = [
[0, 2, INT_MAX, 12, 5],
[2, 0, 4, 8, INT_MAX],
[INT_MAX, 4, 0, 3, 3],
[12, 8, 3, 0, 10],
[5, INT_MAX, 3, 10, 0],
]
TSPUtil(mp)
C#
// C# implementation of the above approach
using System;
using System.Collections.Generic;
using System.Linq;
// Structure of a GNOME
// string defines the path traversed
// by the salesman while the fitness value
// of the path is stored in an integer
public struct Individual
{
public string gnome;
public int fitness;
}
public class TSP
{
// Number of cities in TSP
const int V = 5;
// Names of the cities
const string GENES = "ABCDE";
// Starting Node Value
const int START = 0;
// Initial population size for the algorithm
const int POP_SIZE = 10;
// Function to return a random number
// from start and end
static int RandNum(int start, int end)
{
int r = end - start;
int rnum = start + new Random().Next() % r;
return rnum;
}
// Function to check if the character
// has already occurred in the string
static bool Repeat(string s, char ch)
{
for (int i = 0; i < s.Length; i++)
{
if (s[i] == ch)
return true;
}
return false;
}
// Function to return a mutated GNOME
// Mutated GNOME is a string
// with a random interchange
// of two genes to create variation in species
static string MutatedGene(string gnome)
{
while (true)
{
int r = RandNum(1, V);
int r1 = RandNum(1, V);
if (r1 != r)
{
char[] arr = gnome.ToCharArray();
char temp = arr[r];
arr[r] = arr[r1];
arr[r1] = temp;
gnome = new string(arr);
break;
}
}
return gnome;
}
// Function to return a valid GNOME string
// required to create the population
static string CreateGnome()
{
string gnome = "0";
while (true)
{
if (gnome.Length == V)
{
gnome += gnome[0];
break;
}
int temp = RandNum(1, V);
if (!Repeat(gnome, (char)(temp + 48)))
gnome += (char)(temp + 48);
}
return gnome;
}
// Function to return the fitness value of a gnome.
// The fitness value is the path length
// of the path represented by the GNOME.
static int CalFitness(string gnome)
{
int[,] map = new int[,] {
{ 0, 2, int.MaxValue, 12, 5 },
{ 2, 0, 4, 8, int.MaxValue },
{ int.MaxValue, 4, 0, 3, 3 },
{ 12, 8, 3, 0, 10 },
{ 5, int.MaxValue, 3, 10, 0 }
};
int f = 0;
for (int i = 0; i < gnome.Length - 1; i++)
{
if (map[gnome[i] - 48, gnome[i + 1] - 48] == int.MaxValue)
return int.MaxValue;
f += map[gnome[i] - 48, gnome[i + 1] - 48];
}
return f;
}
// Function to return the updated value
// of the cooling element
static int CoolDown(int temp)
{
return (90 * temp) / 100;
}
// Comparator for GNOME struct.
static bool LessThan(Individual t1, Individual t2)
{
return t1.fitness < t2.fitness;
}
// Utility function for TSP problem.
static void TSPUtil(int[,] map)
{
// Generation Number
int gen = 1;
// Number of Gene Iterations
int gen_thres = 5;
List<Individual> population = new List<Individual>();
Individual temp;
// Populating the GNOME pool.
for (int i = 0; i < POP_SIZE; i++)
{
temp.gnome = CreateGnome();
temp.fitness = CalFitness(temp.gnome);
population.Add(temp);
}
Console.WriteLine("\nInitial population: \nGNOME FITNESS VALUE\n");
foreach (Individual ind in population)
{
Console.WriteLine(ind.gnome + " " + ind.fitness);
}
Console.WriteLine();
bool found = false;
int temperature = 10000;
// Iteration to perform
// population crossing and gene mutation.
while (temperature > 1000 && gen <= gen_thres)
{
population = population.OrderBy(x => x.fitness).ToList();
Console.WriteLine("\nCurrent temp: " + temperature + "\n");
List<Individual> new_population = new List<Individual>();
for (int i = 0; i < POP_SIZE; i++)
{
Individual p1 = population[i];
while (true)
{
string new_g = MutatedGene(p1.gnome);
Individual new_gnome;
new_gnome.gnome = new_g;
new_gnome.fitness = CalFitness(new_gnome.gnome);
if (new_gnome.fitness <= population[i].fitness)
{
new_population.Add(new_gnome);
break;
}
else
{
// Accepting the rejected children at
// a possible probability above threshold.
float prob = (float)Math.Pow(2.7,
-1 * ((float)(new_gnome.fitness
- population[i].fitness)
/ temperature));
if (prob > 0.5)
{
new_population.Add(new_gnome);
break;
}
}
}
}
temperature = CoolDown(temperature);
population = new_population;
Console.WriteLine("Generation " + gen + " \nGNOME FITNESS VALUE\n");
foreach (Individual ind in population)
{
Console.WriteLine(ind.gnome + " " + ind.fitness);
}
gen++;
}
}
static void Main(string[] args)
{
int[,] map = new int[,] { { 0, 2, int.MaxValue, 12, 5 },
{ 2, 0, 4, 8, int.MaxValue },
{ int.MaxValue, 4, 0, 3, 3 },
{ 12, 8, 3, 0, 10 },
{ 5, int.MaxValue, 3, 10, 0 } };
TSPUtil(map);
}
}
JavaScript
// Number of cities in TSP
const V = 5;
// Names of the cities
const GENES = "ABCDE";
// Starting Node Value
const START = 0;
// Initial population size for the algorithm
const POP_SIZE = 10;
// Structure of a GNOME
// string defines the path traversed
// by the salesman while the fitness value
// of the path is stored in an integer
class Individual {
constructor(gnome, fitness) {
this.gnome = gnome;
this.fitness = fitness;
}
}
// Function to return a random number
// from start and end
function rand_num(start, end) {
let r = end - start;
let rnum = start + Math.floor(Math.random() * r);
return rnum;
}
// Function to check if the character
// has already occurred in the string
function repeat(s, ch) {
return s.includes(ch);
}
// Function to return a mutated GNOME
// Mutated GNOME is a string
// with a random interchange
// of two genes to create variation in species
function mutatedGene(gnome) {
while (true) {
let r = rand_num(1, V);
let r1 = rand_num(1, V);
if (r1 !== r) {
let temp = gnome[r];
gnome[r] = gnome[r1];
gnome[r1] = temp;
break;
}
}
return gnome;
}
// Function to return a valid GNOME string
// required to create the population
function create_gnome() {
let gnome = "0";
while (true) {
if (gnome.length === V) {
gnome += gnome[0];
break;
}
let temp = rand_num(1, V);
if (!repeat(gnome, temp.toString())) {
gnome += temp.toString();
}
}
return gnome;
}
// Function to return the fitness value of a gnome.
// The fitness value is the path length
// of the path represented by the GNOME.
function cal_fitness(gnome) {
const map = [
[0, 2, Infinity, 12, 5],
[2, 0, 4, 8, Infinity],
[Infinity, 4, 0, 3, 3],
[12, 8, 3, 0, 10],
[5, Infinity, 3, 10, 0]
];
let f = 0;
for (let i = 0; i < gnome.length - 1; i++) {
if (map[gnome[i]][gnome[i + 1]] === Infinity) {
return Infinity;
}
f += map[gnome[i]][gnome[i + 1]];
}
return f;
}
// Function to return the updated value
// of the cooling element.
function cooldown(temp) {
return (90 * temp) / 100;
}
// Utility function for TSP problem.
function TSPUtil() {
// Generation Number
let gen = 1;
// Number of Gene Iterations
const gen_thres = 5;
let population = [];
// Populating the GNOME pool.
for (let i = 0; i < POP_SIZE; i++) {
let gnome = create_gnome();
let fitness = cal_fitness(gnome);
population.push(new Individual(gnome, fitness));
}
console.log("\nInitial population: ");
population.forEach(individual => {
console.log(`${individual.gnome} ${individual.fitness}`);
});
console.log("\n");
let found = false;
let temperature = 10000;
// Iteration to perform
// population crossing and gene mutation.
while (temperature > 1000 && gen <= gen_thres) {
population.sort((a, b) => a.fitness - b.fitness);
console.log("\nCurrent temp: " + temperature + "\n");
let new_population = [];
for (let i = 0; i < POP_SIZE; i++) {
let p1 = population[i];
while (true) {
let new_g = mutatedGene(p1.gnome);
let new_gnome = new Individual(new_g, cal_fitness(new_g));
if (new_gnome.fitness <= population[i].fitness) {
new_population.push(new_gnome);
break;
} else {
// Accepting the rejected children at
// a possible probability above threshold.
let prob = Math.pow(
2.7,
-1 *
((new_gnome.fitness - population[i].fitness) /
temperature)
);
if (prob > 0.5) {
new_population.push(new_gnome);
break;
}
}
}
}
temperature = cooldown(temperature);
population = new_population;
console.log("Generation " + gen + " \n");
console.log("GNOME FITNESS VALUE\n");
population.forEach(individual => {
console.log(`${individual.gnome} ${individual.fitness}`);
});
gen++;
}
}
// Main function
function main() {
TSPUtil();
}
main();
OutputInitial population:
GNOME FITNESS VALUE
043210 24
023410 2147483647
031420 2147483647
034210 31
043210 24
023140 2147483647
032410 2147483647
012340 24
012340 24
032410 2147483647
Current temp: 10000
Generation 1
GNOME FITNESS VALUE
013240 21
013240 21
012430 31
012430 31
031240 32
024310 2147483647
013420 2147483647
032140 2147483647
034210 31
012430 31
Current temp: 9000
Generation 2
GNOME FITNESS VALUE
031240 32
043210 24
012340 24
042130 32
043210 24
012340 24
034210 31
014320 2147483647
014320 2147483647
023140 2147483647
Current temp: 8100
Generation 3
GNOME FITNESS VALUE
013240 21
042310 21
013240 21
013240 21
031240 32
013240 21
012430 31
034120 2147483647
041320 2147483647
043120 2147483647
Current temp: 7290
Generation 4
GNOME FITNESS VALUE
031240 32
043210 24
043210 24
043210 24
012340 24
042130 32
013240 21
014320 2147483647
021340 2147483647
043210 24
Current temp: 6561
Generation 5
GNOME FITNESS VALUE
043210 24
042310 21
042310 21
013240 21
042310 21
034210 31
013240 21
042310 21
024310 2147483647
024310 2147483647
Time complexity: Â O(n^2) as it uses nested loops to calculate the fitness value of each gnome in the population.Â
Auxiliary Space: O(n)