Esempio n. 1
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);
            }
        }
Esempio n. 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);
        }
Esempio n. 3
0
 //Sorts the newChild object according to its distance from smallest distance to largest distance
 //The List only contains the up to the top "globalVars.maxChildren" children
 public static void sortChild(newChild tempChild, ref globalVars globalVars, ref List <newChild> childList)
 {
     //If the list is empty, add the current child
     if (childList.Count == 0)
     {
         childList.Add(tempChild);
     }
     //If the list is not empty
     else
     {
         //If the list is currently full
         if (childList.Count == globalVars.maxChildren)
         {
             //If the distance of the last child in the list is less than the current child's distance,
             //don't sort the current child and return back to the NewGen class
             if (childList[globalVars.maxChildren - 1].distance < tempChild.distance)
             {
                 return;
             }
             //If the distance of the last child in the list is greater than the current child's distance,
             //sort the current child as it is guarenteed to find a spot in the list
             else
             {
                 //Check all the distances in the list and find where
                 //the current child should be inserted by finding the
                 //first element in the list that has a distance greater than
                 //the current child and insert the child before that element
                 for (int c = 0; c < childList.Count; c++)
                 {
                     if (tempChild.distance == childList[c].distance)
                     {
                         return;
                     }
                     else if (tempChild.distance < childList[c].distance)
                     {
                         childList.Insert(c, tempChild);
                         childList.RemoveAt(globalVars.maxChildren);
                         return;
                     }
                 }
             }
         }
         //If the list is not full,
         //sort the current child as it is guarenteed to find a spot in the list
         else
         {
             //Check all the distances in the list and find where
             //the current child should be inserted by finding the
             //first element in the list that has a distance greater than
             //the current child and insert the child before that element
             for (int c = 0; c < childList.Count; c++)
             {
                 if (tempChild.distance == childList[c].distance)
                 {
                     return;
                 }
                 else if (tempChild.distance < childList[c].distance)
                 {
                     childList.Insert(c, tempChild);
                     return;
                 }
                 //If the current child needs to be the
                 //last item in the list for the first time
                 else if (c == childList.Count - 1)
                 {
                     childList.Add(tempChild);
                     return;
                 }
             }
         }
     }
 }
Esempio n. 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();
        }