Beispiel #1
0
        //Sets up for the pmx crossover thats implemented in the NewGenChild class
        public static newChild newGen(newCity[] cityArray, ref globalVars globalVars, ref List <newChild>[] genList)
        {
            //Random variables/functions
            int    rand = 0;
            Random rnd  = new Random();
            Random rnd2 = new Random(Guid.NewGuid().GetHashCode());

            //Temp lists to feed the newGenChild function to execute the pmx crossover
            List <int> temp1     = new List <int>();
            List <int> temp2     = new List <int>();
            List <int> pmx1      = new List <int>();
            List <int> pmx2      = new List <int>();
            List <int> tempFinal = new List <int>();

            //Copy the best parent from the current generation to the next generation
            if (globalVars.genVar == 0)
            {
                SortChild.sortChild(((genList[0])[0]), ref globalVars, ref genList[1]);
            }
            else
            {
                SortChild.sortChild(((genList[1])[0]), ref globalVars, ref genList[0]);
            }

            //Do for each parent in the current generation
            for (int i = 0; i < genList[globalVars.genVar].Count; i++)
            {
                //Variable to stop an infinte loop when trying
                //to find unique substrings from the parents
                int help = 0;

                //Clear temp lists
                temp1.Clear();
                temp2.Clear();
                tempFinal.Clear();
                pmx1.Clear();
                pmx2.Clear();

                //Parent 1, which will be all the parents
                //in the current generation
                temp1.AddRange(((genList[globalVars.genVar])[i]).path);
                temp1.RemoveAt(temp1.Count - 1);

                //Randomly pick parent 2 while checking that
                //it's not parent 1
                rand = rnd.Next(0, genList[globalVars.genVar].Count);
                while (((rand = rnd.Next(0, genList[globalVars.genVar].Count)) == i))
                {
                }
                temp2.AddRange(((genList[globalVars.genVar])[rand]).path);
                temp2.RemoveAt(temp2.Count - 1);

                //Generate the substrings starting at a random point
                //in the lists with globalVars.pmx length
                rand = rnd.Next(0, temp1.Count - globalVars.pmx);
                for (int p = rand; p < (rand + globalVars.pmx); p++)
                {
                    pmx1.Add(temp1[p]);
                    pmx2.Add(temp2[p]);
                }

                //Checks to make sure the substrings are not equal
                //to prevent the crossover from doing nothing
                //Will only attempt 100 times before exiting
                //to prevent infine loops when both parents are equal
                while ((pmx1.SequenceEqual(pmx2) == true) && (help < 100))
                {
                    pmx1.Clear();
                    pmx2.Clear();
                    rand = rnd.Next(1, temp1.Count - globalVars.pmx);
                    for (int p = rand; p < (rand + globalVars.pmx); p++)
                    {
                        pmx1.Add(temp1[p]);
                        pmx2.Add(temp2[p]);
                    }
                    help++;
                }

                //Call the newGenChild function to perform the pmx crossover
                //on both parents with the other parents subsections to create 2 new children
                //rand2 is used to determine if mutation will occur within the function
                double rand2 = rnd2.NextDouble();
                NewGenChild.newGenChild(cityArray, ref globalVars, ref genList, rand, temp1, pmx2, rand2);
                rand2 = rnd2.NextDouble();
                NewGenChild.newGenChild(cityArray, ref globalVars, ref genList, rand, temp2, pmx1, rand2);
            }

            //Once all the children have been created
            //Swap the globalVar.genVar so that the new
            //children become the new parents and the current
            //parents are cleared to make space for the next generation of children
            //The best child from the generation is then returned to determine
            //if the generation inproved fitness
            if (globalVars.genVar == 0)
            {
                globalVars.genVar = 1;
                genList[0].Clear();
                return((genList[1])[0]);
            }
            else
            {
                globalVars.genVar = 0;
                genList[1].Clear();
                return((genList[0])[0]);
            }
        }
Beispiel #2
0
        public static void newGenChild(newCity[] cityArray, ref globalVars globalVars, ref List <newChild>[] genList, int rand, List <int> _tempList, List <int> _altPmx, double rand2)
        {
            //Temp variables
            int   index;
            int   tempVar;
            float distance      = 0;
            float totalDistance = 0;

            //Random function and temp lists
            Random     rnd      = new Random(Guid.NewGuid().GetHashCode());
            List <int> tempList = new List <int>(_tempList);
            List <int> altPmx   = new List <int>(_altPmx);
            List <int> tempMut  = new List <int>();

            //Performs the pmx crossover by swapping the cities in the
            //parent's list according to the sublist from the other parent
            for (int j = rand; j < rand + globalVars.pmx; j++)
            {
                tempVar = tempList[j];
                index   = tempList.IndexOf(altPmx[j - rand]);
                tempList.RemoveAt(index);
                tempList.Insert(index, tempVar);
                tempList.RemoveAt(j);
                tempList.Insert(j, altPmx[j - rand]);
            }

            //Performs inversion mutation if rand2 was less than
            //the globalVars.mutation/100
            if (rand2 < (globalVars.mutation / 100))
            {
                tempMut.Clear();
                rand = rnd.Next(1, tempList.Count - globalVars.pmx);
                for (int k = rand; k < rand + globalVars.pmx; k++)
                {
                    tempMut.Add(tempList[k]);
                    tempList.RemoveAt(k);
                    tempList.Insert(rand, tempMut[k - rand]);
                }
            }

            tempList.Add(tempList[0]);

            //Calculate the tour distance
            for (int d = 1; d < tempList.Count; d++)
            {
                int xy1 = tempList[d - 1] - 1; //Location of city A in city List
                int xy2 = tempList[d] - 1;     //Location of city B in city List

                //Find x and y coordinates of city A and B
                float x1 = cityArray[xy1].xCoordinate;
                float x2 = cityArray[xy2].xCoordinate;
                float y1 = cityArray[xy1].yCoordinate;
                float y2 = cityArray[xy2].yCoordinate;

                //Use distance equation to find the distance between city A and B
                //Add distance to totalDistance
                distance      = (float)Math.Sqrt((((x2 - x1)) * (x2 - x1)) + ((y2 - y1) * (y2 - y1)));
                totalDistance = totalDistance + distance;
            }

            //Create newChild with tempList path and corresponding distance
            newChild tempChild = new newChild(totalDistance, tempList);

            //Sort the tempChild node in the not current parent genList
            if (globalVars.genVar == 0)
            {
                SortChild.sortChild(tempChild, ref globalVars, ref genList[1]);
            }
            else
            {
                SortChild.sortChild(tempChild, ref globalVars, ref genList[0]);
            }
            //Sort child into the wisdomList to be used for WOC
            SortChild.sortChild(tempChild, ref globalVars, ref globalVars.wisdomList);
        }
Beispiel #3
0
        //Same the Split function about but splits the map at x coordinates instead of y coordinates
        public static void splitX(newCity[] cityArray, float split, ref globalVars globalVars, ref List <newChild> childList)
        {
            //Distance variables
            float distance      = 0;
            float totalDistance = 0;

            float distanceTL = 0;       //Top Left distance
            float distanceTR = 0;       //Top Right distance
            float distanceBR = 0;       //Bottom Right Distance
            float distanceBL = 0;       //Bottom Left distance

            //newCorner objects to find the 4 corners
            newCorner topLeft     = new newCorner(float.MaxValue);
            newCorner topRight    = new newCorner(float.MaxValue);
            newCorner bottomLeft  = new newCorner(float.MaxValue);
            newCorner bottomRight = new newCorner(float.MaxValue);

            //Lists to store the cities above and below the split point
            List <int> topList     = new List <int>();
            List <int> topFinal    = new List <int>();
            List <int> bottomList  = new List <int>();
            List <int> bottomFinal = new List <int>();

            //Check each city in the cityArray to see if it's
            //above or below the split point
            for (int c = 1; c < cityArray.Length + 1; c++)
            {
                //Above the split point
                if (cityArray[c - 1].xCoordinate > split)
                {
                    topList.Add(c);     //Add to the topList

                    //Find cities closest to (split, 0) and (split, 100)
                    float x1 = cityArray[c - 1].xCoordinate;
                    float y1 = cityArray[c - 1].yCoordinate;
                    float x2 = split;
                    float y2 = 0;
                    float y3 = 100;
                    distanceBR = (float)Math.Sqrt((((x2 - x1)) * (x2 - x1)) + ((y2 - y1) * (y2 - y1)));
                    distanceTR = (float)Math.Sqrt((((x2 - x1)) * (x2 - x1)) + ((y3 - y1) * (y3 - y1)));

                    //Check if the city is closest to (split, 0) and (split, 100)
                    if (distanceTL < topLeft.coordinate)
                    {
                        topLeft.id         = c;
                        topLeft.coordinate = distanceTL;
                    }
                    if (distanceTR < topRight.coordinate)
                    {
                        topRight.id         = c;
                        topRight.coordinate = distanceTR;
                    }
                }

                //At or below the split point
                else
                {
                    bottomList.Add(c);  //Add to the bottom list

                    //Find cities closest to (split, 0) and (split, 100)
                    float x1 = cityArray[c - 1].xCoordinate;
                    float y1 = cityArray[c - 1].yCoordinate;
                    float x2 = split;
                    float y2 = 0;
                    float y3 = 100;
                    distanceBL = (float)Math.Sqrt((((x2 - x1)) * (x2 - x1)) + ((y2 - y1) * (y2 - y1)));
                    distanceTL = (float)Math.Sqrt((((x2 - x1)) * (x2 - x1)) + ((y3 - y1) * (y3 - y1)));

                    //Check if the city is closest to (split, 0) and (split, 100)
                    if (distanceBL < bottomLeft.coordinate)
                    {
                        bottomLeft.id         = c;
                        bottomLeft.coordinate = distanceBL;
                    }
                    if (distanceBR < bottomRight.coordinate)
                    {
                        bottomRight.id         = c;
                        bottomRight.coordinate = distanceBR;
                    }
                }
            }

            //Discard current split if it resulted in a single city being
            //both bottomRight/bottomLeft or topRight/topLeft
            if ((topList.Count <= 1) || (bottomList.Count <= 1))
            {
                return;
            }

            //Adding the corner cities to the top/bottomFinal lists
            //Removing the corner cities from the top/bottom lists
            topFinal.Add(topLeft.id);
            topFinal.Add(topRight.id);
            bottomFinal.Add(bottomRight.id);
            bottomFinal.Add(bottomLeft.id);
            topList.Remove(topLeft.id);
            topList.Remove(topRight.id);
            bottomList.Remove(bottomLeft.id);
            bottomList.Remove(bottomRight.id);

            //Call insertNode function to generate the new greedy paths
            InsertNode.insertNode(cityArray, topList, ref topFinal);
            InsertNode.insertNode(cityArray, bottomList, ref bottomFinal);

            //Combine the top and bottom paths to complete the tour
            topFinal.AddRange(bottomFinal);
            topFinal.Add(topFinal[0]);

            //If the path's distance wasn't the most recent path to be computed
            //find the distance of the path
            if (topFinal.SequenceEqual(globalVars.lastPath) == false)
            {
                globalVars.unique++;
                for (int d = 1; d < topFinal.Count; d++)
                {
                    int xy1 = topFinal[d - 1] - 1; //Location of city A in city List
                    int xy2 = topFinal[d] - 1;     //Location of city B in city List

                    //Find x and y coordinates of city A and B
                    float x1 = cityArray[xy1].xCoordinate;
                    float x2 = cityArray[xy2].xCoordinate;
                    float y1 = cityArray[xy1].yCoordinate;
                    float y2 = cityArray[xy2].yCoordinate;

                    //Use distance equation to find the distance between city A and B
                    //Add distance to totalDistance
                    distance      = (float)Math.Sqrt((((x2 - x1)) * (x2 - x1)) + ((y2 - y1) * (y2 - y1)));
                    totalDistance = totalDistance + distance;
                }

                //Store the most recent path to avoid
                //computing the same path multiple times
                globalVars.lastPath = topFinal;

                //Create newChild with topFinal path and corresponding distance
                newChild tempChild = new newChild(totalDistance, topFinal);

                //Rearange the tempChilds path so that it starts and ends with "1"
                tempChild.path.RemoveAt(topFinal.Count - 1);
                for (int i = 0; i < tempChild.path.Count; i++)
                {
                    i = 0;
                    if (tempChild.path[0] == 1)
                    {
                        break;
                    }
                    else
                    {
                        tempChild.path.Add(tempChild.path[0]);
                        tempChild.path.RemoveAt(0);
                    }
                }
                tempChild.path.Add(tempChild.path[0]);

                //If the new path distance is smaller than the
                //current smallest distance then replace
                //the smallest distance with the new distance
                if (tempChild.distance < globalVars.shortDistance)
                {
                    globalVars.shortList.Clear();
                    globalVars.shortDistance = tempChild.distance; //Store the new shorter distance
                    globalVars.shortList.AddRange(tempChild.path); //Store the corresponding path
                    globalVars.shortSplit = split;                 //Store the current split value
                }

                //Sort the tempChild
                SortChild.sortChild(tempChild, ref globalVars, ref childList);
                SortChild.sortChild(tempChild, ref globalVars, ref globalVars.wisdomList);
            }
        }
Beispiel #4
0
        static void Main(string[] args)
        {
            //Code needed to run the Windows Form Application
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            string fileName = "Random22.TSP";    //File name being tested

            //Variables to keep track of execution time
            Stopwatch stopWatch = new Stopwatch();
            float     time1     = 0;
            string    time2     = null;
            string    timer     = null;

            stopWatch.Start();      //Start Stopwatch

            //Temp float to keep track of
            //shortest distance of each generation
            float  tempDistance  = float.MaxValue;
            int    z             = 0; //Temp variable
            int    gen           = 0; //Keeps track of current generation
            int    count         = 0; //Count variable
            double split         = 2; //Split variables
            float  split2        = 0;
            float  distance      = 0; //Distance variables
            float  totalDistance = 0;

            globalVars globalVars = new globalVars();            //Object to hold "global" variables

            List <newChild>[] genList = new List <newChild> [2]; //Array to hold the children of each generation
            genList[0] = new List <newChild>();                  //Swaps between holding the parents and children of a generation
            genList[1] = new List <newChild>();                  //Swaps between holding the parents and children of a generation

            //Reads file to find # of lines
            //Stores (# of lines  - 7) to get the number of cities in the file
            string[] lines     = File.ReadAllLines(fileName);
            int      newLength = lines.Length - 7;

            //Array of newCity objects with size = # of cities
            newCity[] cityArray = new newCity[newLength];

            //Stores city data
            string line;

            System.IO.StreamReader file = new System.IO.StreamReader(fileName);
            while ((line = file.ReadLine()) != null)
            {
                //Ignore first 7 lines of the file
                //8th line is where the city data begins
                if (count >= 7)
                {
                    string[] data = line.Split(' ');    //Split and store the city data in data string array

                    //Create newCity object using data pulled from data array (ID, x Coordinate, y Coordinate)
                    //Store each newCity object in newCity array
                    cityArray[count - 7] = new newCity(Int32.Parse(data[0]), float.Parse(data[1]), float.Parse(data[2]));
                }
                count++;
            }
            //Close File
            file.Close();

            //If input for GA is choosen to be random
            if (globalVars.random == true)
            {
                Console.WriteLine("Random Inputs");
                Random     rnd   = new Random();
                List <int> temp1 = new List <int>();  //Temp list

                //Create a list with all the cities in it
                for (int l = 0; l < newLength; l++)
                {
                    temp1.Add(cityArray[l].id);
                }
                temp1.RemoveAt(0);      //Remove "1" from the list

                //Create "population size" of random tours
                for (int r = 0; r < globalVars.maxChildren; r++)
                {
                    List <int> temp2 = new List <int>(temp1);
                    int        n     = temp2.Count;

                    //Scramble the list containing the cities
                    while (n > 1)
                    {
                        n--;
                        int rand = rnd.Next(n + 1);
                        z           = temp2[rand];
                        temp2[rand] = temp2[n];
                        temp2[n]    = z;
                    }

                    //Add "1" to the start and end of the list to complete the tour
                    temp2.Insert(0, 1);
                    temp2.Add(1);

                    //Calculate the tour distance
                    for (int d = 1; d < temp2.Count; d++)
                    {
                        int xy1 = temp2[d - 1] - 1; //Location of city A in city List
                        int xy2 = temp2[d] - 1;     //Location of city B in city List

                        //Find x and y coordinates of city A and B
                        float x1 = cityArray[xy1].xCoordinate;
                        float x2 = cityArray[xy2].xCoordinate;
                        float y1 = cityArray[xy1].yCoordinate;
                        float y2 = cityArray[xy2].yCoordinate;

                        //Use distance equation to find the distance between city A and B
                        //Add distance to totalDistance
                        distance      = (float)Math.Sqrt((((x2 - x1)) * (x2 - x1)) + ((y2 - y1) * (y2 - y1)));
                        totalDistance = totalDistance + distance;
                    }

                    //Create the newChild object using the randomized list
                    //and the corresponding distance and then sort the child in genList[0]
                    newChild tempChild = new newChild(totalDistance, temp2);
                    SortChild.sortChild(tempChild, ref globalVars, ref genList[0]);
                }
            }

            //If input for GA is choosen to use the tours found by the greedy algorithm
            else
            {
                Console.WriteLine("Greedy Inputs");
                //Split the map of cities at y = split and x = split
                //to generate solutions to use as the initial parents for the GA
                for (split = 2; split < 100; split += 0.5)
                {
                    split2 = Convert.ToSingle(split);
                    //Call the split function to split the map of cities at y = split
                    Split.splitY(cityArray, split2, ref globalVars, ref genList[0]);
                    //Call the split function to split the map of cities at x = split
                    Split.splitX(cityArray, split2, ref globalVars, ref genList[0]);
                }
            }

            //Calls GA functions until the same distance
            //of the top child is found "globalVars.sameGen" times
            Console.WriteLine("Start GA");
            for (z = 0; z < globalVars.sameGen; z++)
            {
                gen++;      //Keeps track of the current generation

                //Calls newGen function to create the next generation
                //and return the child with the shortest distance
                newChild topChild = NewGen.newGen(cityArray, ref globalVars, ref genList);

                //Checks if the top child from the generation is more fit
                //than the top child from the last generation
                tempDistance = topChild.distance;
                //Console.WriteLine("gen " + gen + "          " + tempDistance);
                if (tempDistance < globalVars.shortDistance)
                {
                    //If the child is more fit than the previous generation
                    //set the new distance as the shorest distance
                    //and reset the GA stop condition
                    z = 0;
                    globalVars.shortDistance = tempDistance;
                    globalVars.shortList.Clear();
                    globalVars.shortList.AddRange(topChild.path);
                }
            }

            //Prints the shortest tour/distance before the wisdom of crowds function is called
            Console.WriteLine("The Old Distance is " + globalVars.shortDistance);
            Console.WriteLine("The Old Path is " + string.Join(",", globalVars.shortList));
            globalVars.shortDistance = 0;
            globalVars.shortList.Clear();

            //Calls the Wisdom of Crowds function
            Console.WriteLine("Start WOC");
            Console.WriteLine("WOC List Length = " + globalVars.wisdomList.Count);
            Crowds.crowds(newLength, ref globalVars);

            //Finds the distance for the Wisdom of Crowds tour
            for (int d = 1; d < globalVars.shortList.Count; d++)
            {
                int xy1 = globalVars.shortList[d - 1] - 1; //Location of city A in city List
                int xy2 = globalVars.shortList[d] - 1;     //Location of city B in city List

                //If the WOC algorithm produced an imcomplete tour (not likely),
                //restart the application to find a clean solution
                //Bad solutions occurs when the WOC algorithm finds
                //an index that has no cities in it (all cities at index i are set to 0)
                if (xy1 < 0 || xy2 < 0)
                {
                    Console.WriteLine("Bad Solution");
                    Console.WriteLine("Press any key to restart");
                    Console.ReadKey();
                    Application.Restart();
                    Environment.Exit(0);
                }

                //Find x and y coordinates of city A and B
                float x1 = cityArray[xy1].xCoordinate;
                float x2 = cityArray[xy2].xCoordinate;
                float y1 = cityArray[xy1].yCoordinate;
                float y2 = cityArray[xy2].yCoordinate;

                //Use distance equation to find the distance between city A and B
                //Add distance to totalDistance
                distance      = (float)Math.Sqrt((((x2 - x1)) * (x2 - x1)) + ((y2 - y1) * (y2 - y1)));
                totalDistance = totalDistance + distance;
            }
            globalVars.shortDistance = totalDistance;

            stopWatch.Stop();   //Stop Stopwatch

            //Print distance/path/time data
            Console.WriteLine("File = " + fileName);
            Console.WriteLine("The New Distance is " + globalVars.shortDistance);
            Console.WriteLine("The New Path is " + string.Join(",", globalVars.shortList));
            time1 = stopWatch.ElapsedMilliseconds;
            time1 = (float)TimeSpan.FromMilliseconds(time1).TotalSeconds;
            time2 = stopWatch.ElapsedMilliseconds.ToString();
            timer = time1.ToString();
            Console.WriteLine("Execution time took " + time2 + " Milliseconds, or " + timer + " Seconds");

            //Run Windows Form Application to graph the shortest path
            Application.Run(new GUI(cityArray, globalVars.shortList));
            //Application.Restart();
            //Environment.Exit(0);
            Console.ReadKey();
        }