Advertisement
Guest User

Untitled

a guest
Aug 1st, 2018
22
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 10.59 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. namespace GAExample
  5. {
  6.     class Program
  7.     {
  8.         static void Main(string[] args)
  9.         {
  10.             //Generate knapsack instance with 50 items with an max item weight of 100
  11.             KnapSackInstance knapSack = new KnapSackInstance(50, 0.5, 100);
  12.             knapSack.Print();
  13.             Console.WriteLine("Press enter to start the genetic algorithm and again to go to the next generation");
  14.             Console.ReadLine();
  15.             GeneticAlgorithm GA = new GeneticAlgorithm(knapSack, 50);
  16.            
  17.             while (true)
  18.             {
  19.                 GA.Print();
  20.                 GA.NextGeneration();
  21.                 Console.ReadLine();
  22.             }
  23.         }
  24.  
  25.  
  26.     }
  27.     class GeneticAlgorithm
  28.     {
  29.         public List<Solution> Population;
  30.         public Solution OptimalSolution;
  31.         Random RNG = new Random();
  32.         public GeneticAlgorithm(KnapSackInstance knapSack, int popSize)
  33.         {
  34.             //Create population with random solutions and aply hill climbing
  35.             Population = new List<Solution>();
  36.             for (int i = 0; i < popSize; i++)
  37.             {
  38.                 Solution individual = new Solution(knapSack);
  39.                 individual.HillClimb();
  40.                 Population.Add(individual);
  41.             }
  42.  
  43.  
  44.             //Generate optimal solution for reference
  45.             OptimalSolution = new Solution(knapSack);
  46.             OptimalSolution.DynamicFill();
  47.         }
  48.         public void NextGeneration()
  49.         {
  50.             int popSize = Population.Count;
  51.  
  52.             List<Solution> Childeren = new List<Solution>();
  53.             while (Childeren.Count < popSize)
  54.             {
  55.                 //pick two random parents
  56.                 Solution parent1 = Population[RNG.Next(Population.Count)];
  57.                 Solution parent2 = Population[RNG.Next(Population.Count)];
  58.  
  59.                 //apply uniform crossover to get offspring
  60.                 Solution child = parent1.UniformCrossover(parent2);
  61.                 Childeren.Add(child);
  62.             }
  63.             foreach (Solution child in Childeren)
  64.             {
  65.                 //perform hillclimbing on offspring
  66.                 child.HillClimb();
  67.             }
  68.  
  69.             // add offspring to population
  70.             Population.AddRange(Childeren);
  71.  
  72.             //apply truncation selection i.e. throw worst half away
  73.             Population = Population.OrderByDescending(x => x.GetFitness()).Take(popSize).ToList();
  74.         }
  75.  
  76.         public void Print()
  77.         {
  78.             Console.WriteLine("Global Optimum/ Target Soltion:");
  79.             OptimalSolution.Print();
  80.             Console.WriteLine("Population:");
  81.             foreach (var individual in Population)
  82.             {
  83.                 individual.Print();
  84.  
  85.             }
  86.             Console.WriteLine();
  87.         }
  88.     }
  89.  
  90.     class Solution
  91.     {
  92.         public bool[] BitString;
  93.         public KnapSackInstance KnapSack;
  94.         Random RNG;
  95.         public Solution(KnapSackInstance knapSack)
  96.         {
  97.             KnapSack = knapSack;
  98.             BitString = new bool[KnapSack.Items.Count];
  99.             RNG = knapSack.RNG;
  100.         }
  101.  
  102.         public void RandomInitialize()
  103.         {
  104.             //generates random soltion
  105.             for (int i = 0; i < BitString.Length; i++)
  106.             {
  107.                 BitString[i] = RNG.NextDouble() > 0.5;
  108.             }
  109.         }
  110.  
  111.         public void RandomFix()
  112.         {
  113.             //removes random items until the capacity contraint is met
  114.             List<int> indices = new List<int>();
  115.             int totalWeight = 0;
  116.             for (int i = 0; i < BitString.Length; i++)
  117.             {
  118.                 if (BitString[i]) { indices.Add(i); totalWeight += KnapSack.Items[i].Weight; }
  119.             }
  120.             while (totalWeight > KnapSack.MaxWeight)
  121.             {
  122.                 int randomIndex = RNG.Next(indices.Count);
  123.                 int index = indices[randomIndex];
  124.                 indices.RemoveAt(randomIndex);
  125.                 BitString[index] = false;
  126.                 totalWeight -= KnapSack.Items[index].Weight;
  127.             }
  128.         }
  129.  
  130.  
  131.         //applies bitflip unti no improving moves are made
  132.         public void HillClimb()
  133.         {
  134.  
  135.             while (BitFlip()) { }
  136.         }
  137.  
  138.         //Sees if there is a bitflip possible the produces a better solution
  139.         //This process is randomized for diversity in population
  140.         public bool BitFlip()
  141.         {
  142.             List<int> indices = new List<int>();
  143.             int totalWeight = 0;
  144.             for (int i = 0; i < BitString.Length; i++)
  145.             {
  146.                 indices.Add(i);
  147.                 if (BitString[i]) { totalWeight += KnapSack.Items[i].Weight; }
  148.             }
  149.             indices = indices.OrderBy(x => RNG.NextDouble()).ToList();
  150.             foreach (int index in indices)
  151.             {
  152.                 int fitness = KnapSack.GetFitness(BitString);
  153.                 BitString[index] = !BitString[index];
  154.                 if (fitness >= KnapSack.GetFitness(BitString))
  155.                 {
  156.                     BitString[index] = !BitString[index];
  157.                 }
  158.                 else
  159.                 {
  160.                     return true;
  161.                 }
  162.             }
  163.             return false;
  164.         }
  165.  
  166.         // generates offspring with the uniform crossover
  167.         public Solution UniformCrossover(Solution parent2)
  168.         {
  169.             bool[] newBitString = new bool[BitString.Length];
  170.             for (int i = 0; i < BitString.Length; i++)
  171.             {
  172.                 newBitString[i] = RNG.NextDouble() > 0.5 ? BitString[i] : parent2.BitString[i];
  173.             }
  174.             Solution child = new Solution(KnapSack);
  175.             child.BitString = newBitString;
  176.             child.RandomFix();
  177.             return child;
  178.         }
  179.  
  180.         public int GetFitness()
  181.         {
  182.             return KnapSack.GetFitness(BitString);
  183.         }
  184.  
  185.         //Find optimal solution with dynamic programming
  186.         //No comments (sorry) so probabily not easy to understand
  187.         public void DynamicFill()
  188.         {
  189.             double[,] matrix = new double[BitString.Length, KnapSack.MaxWeight + 1];
  190.             for (int i = 0; i <= KnapSack.MaxWeight; i++)
  191.             {
  192.                 matrix[0, i] = Int32.MinValue;
  193.             }
  194.  
  195.             bool[] bits = new bool[BitString.Length];
  196.             matrix[0, 0] = 0;
  197.             matrix[0, KnapSack.Items[0].Weight] = KnapSack.Items[0].Profit;
  198.  
  199.             for (int i = 1; i < BitString.Length; i++)
  200.             {
  201.                 for (int j = 0; j <= KnapSack.MaxWeight; j++)
  202.                 {
  203.                     double notInclude = matrix[i - 1, j];
  204.                     double Include;
  205.                     if (j - KnapSack.Items[i].Weight >= 0)
  206.                     {
  207.                         Include = matrix[i - 1, j - KnapSack.Items[i].Weight] + KnapSack.Items[i].Profit;
  208.                     }
  209.                     else
  210.                     {
  211.                         Include = Int32.MinValue;
  212.                     }
  213.                     matrix[i, j] = Include >= notInclude ? Include : notInclude;
  214.                 }
  215.             }
  216.  
  217.             //find best value in last column
  218.             double best = Int32.MinValue;
  219.             int weight = 0;
  220.             for (int j = 0; j <= KnapSack.MaxWeight; j++)
  221.             {
  222.                 if (matrix[BitString.Length - 1, j] > best)
  223.                 {
  224.                     best = matrix[BitString.Length - 1, j];
  225.                     weight = j;
  226.                 }
  227.             }
  228.  
  229.             //Extract the best packing plan
  230.             {
  231.                 int j = weight;
  232.                 for (int i = BitString.Length - 1; i > 0; i--)
  233.                 {
  234.                     double notInclude = matrix[i - 1, j];
  235.                     double Include;
  236.                     if (j - KnapSack.Items[i].Weight >= 0)
  237.                     {
  238.                         Include = matrix[i - 1, j - KnapSack.Items[i].Weight] + KnapSack.Items[i].Profit;
  239.                     }
  240.                     else
  241.                     {
  242.                         Include = Int32.MinValue;
  243.                     }
  244.                     if (Include >= notInclude)
  245.                     {
  246.                         bits[i] = true;
  247.                         j = j - KnapSack.Items[i].Weight;
  248.                     }
  249.                 }
  250.  
  251.                 if (j > 0)
  252.                 {
  253.                     bits[0] = true;
  254.                 }
  255.             }
  256.             BitString = bits;
  257.         }
  258.         public void Print()
  259.         {
  260.             string bitsRepresentation = "";
  261.             for (int i = 0; i < BitString.Length; i++)
  262.             {
  263.                 bitsRepresentation += BitString[i] ? 1 : 0;
  264.             }
  265.             Console.WriteLine(GetFitness() + " : " + bitsRepresentation);
  266.         }
  267.  
  268.     }
  269.     class Item
  270.     {
  271.         public int Weight;
  272.         public int Profit;
  273.         public Item(int weight, int profit)
  274.         {
  275.             Weight = weight;
  276.             Profit = profit;
  277.         }
  278.     }
  279.     class KnapSackInstance
  280.     {
  281.  
  282.         public List<Item> Items;
  283.         public int MaxWeight;
  284.         public Random RNG = new Random();
  285.  
  286.         //creates random knapsack intance of type (weakly) correlated
  287.         public KnapSackInstance(int maxItems, double maxWeightFactor, int maxWeightItem)
  288.         {
  289.  
  290.             int totalWeight = 0;
  291.             Items = new List<Item>();
  292.             for (int i = 0; i < maxItems; i++)
  293.             {
  294.                 int weight = RNG.Next(maxWeightItem);
  295.                 int profit = weight + RNG.Next(10);
  296.                 Items.Add(new Item(weight, profit));
  297.                 totalWeight += weight;
  298.             }
  299.             MaxWeight = (int)(totalWeight * maxWeightFactor);
  300.         }
  301.  
  302.         public int GetFitness(bool[] solution)
  303.         {
  304.             int weight = 0;
  305.             int profit = 0;
  306.             for (int i = 0; i < solution.Length; i++)
  307.             {
  308.                 if (solution[i])
  309.                 {
  310.                     profit += Items[i].Profit;
  311.                     weight += Items[i].Weight;
  312.                 }
  313.             }
  314.  
  315.             return weight <= MaxWeight ? profit : int.MinValue;
  316.         }
  317.  
  318.         public void Print()
  319.         {
  320.             Console.WriteLine("All items:");
  321.             Console.WriteLine("Index\tProfit\tWeight");
  322.             for (int i = 0; i < Items.Count; i++)
  323.             {
  324.                 Console.WriteLine("{0}\t{1}\t{2}", i, Items[i].Profit, Items[i].Weight);
  325.             }
  326.  
  327.         }
  328.     }
  329.  
  330.  
  331. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement