Advertisement
Guest User

GENOTIP.cs

a guest
Sep 23rd, 2012
131
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 18.28 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5.  
  6. // from pastebin
  7. namespace Kromo
  8. {
  9.     public class Genotip
  10.     {
  11.         // CM --
  12.         // 4 dimensional polynomial approximation
  13.         private static double[,] rez_pokusa = new double[15, 4];
  14.         static Genotip()
  15.         {   // Rezultati pokusa
  16.  
  17.             // CM -- these are the sample points (x,y,z) and the resulting value I'll call (w)
  18.             rez_pokusa[0, 0] = 165; rez_pokusa[0, 1] = 0.3; rez_pokusa[0, 2] = 2.0; rez_pokusa[0, 3] = 0.56;
  19.             rez_pokusa[1, 0] = 180; rez_pokusa[1, 1] = 0.24; rez_pokusa[1, 2] = 2.7; rez_pokusa[1, 3] = 0.34;
  20.             rez_pokusa[2, 0] = 165; rez_pokusa[2, 1] = 0.3; rez_pokusa[2, 2] = 0.82; rez_pokusa[2, 3] = 0.42;
  21.             rez_pokusa[3, 0] = 190; rez_pokusa[3, 1] = 0.3; rez_pokusa[3, 2] = 2.0; rez_pokusa[3, 3] = 0.45;
  22.             rez_pokusa[4, 0] = 165; rez_pokusa[4, 1] = 0.4; rez_pokusa[4, 2] = 2.0; rez_pokusa[4, 3] = 1.15;
  23.             rez_pokusa[5, 0] = 165; rez_pokusa[5, 1] = 0.2; rez_pokusa[5, 2] = 2.0; rez_pokusa[5, 3] = 0.23;
  24.             rez_pokusa[6, 0] = 180; rez_pokusa[6, 1] = 0.36; rez_pokusa[6, 2] = 2.7; rez_pokusa[6, 3] = 0.88;
  25.             rez_pokusa[7, 0] = 150; rez_pokusa[7, 1] = 0.36; rez_pokusa[7, 2] = 1.3; rez_pokusa[7, 3] = 0.97;
  26.             rez_pokusa[8, 0] = 150; rez_pokusa[8, 1] = 0.24; rez_pokusa[8, 2] = 2.7; rez_pokusa[8, 3] = 0.47;
  27.             rez_pokusa[9, 0] = 140; rez_pokusa[9, 1] = 0.3; rez_pokusa[9, 2] = 2.0; rez_pokusa[9, 3] = 0.92;
  28.             rez_pokusa[10, 0] = 150; rez_pokusa[10, 1] = 0.24; rez_pokusa[10, 2] = 1.3; rez_pokusa[10, 3] = 0.39;
  29.             rez_pokusa[11, 0] = 180; rez_pokusa[11, 1] = 0.36; rez_pokusa[11, 2] = 1.3; rez_pokusa[11, 3] = 0.77;
  30.             rez_pokusa[12, 0] = 150; rez_pokusa[12, 1] = 0.36; rez_pokusa[12, 2] = 2.7; rez_pokusa[12, 3] = 1.1;
  31.             rez_pokusa[13, 0] = 165; rez_pokusa[13, 1] = 0.3; rez_pokusa[13, 2] = 3.18; rez_pokusa[13, 3] = 0.81;
  32.             rez_pokusa[14, 0] = 180; rez_pokusa[14, 1] = 0.24; rez_pokusa[14, 2] = 1.3; rez_pokusa[14, 3] = 0.28;
  33.         }
  34.        
  35.         public List<Kromosom> kromosom;
  36.         Random random;
  37.         private const double a = 0.7;
  38.        
  39.         public Genotip(int nrOfChro)
  40.         {
  41.             kromosom = new List<Kromosom>();
  42.             random = new Random();
  43.            
  44.             for (int i = 0; i < nrOfChro; i++)
  45.                 kromosom.Add(new Kromosom(random));
  46.         }
  47.  
  48.         // CM add evaluation function for re-use in charting the results in the output files
  49.         // return - computed value for this sample
  50.         // parameters
  51.         // k - chromosome to evaluate
  52.         // sample_index - which sample to test
  53.         // actual - [out] the actual sample value
  54.         public double eval(Kromosom k, int sample_index, out double actual)
  55.         {
  56.             int i = sample_index;
  57.  
  58.             // CM - 4D polynomial approximation
  59.             double guess = k.Alele[0]
  60.                 + k.Alele[1] * rez_pokusa[i, 0]
  61.                 + k.Alele[2] * rez_pokusa[i, 1]
  62.                 + k.Alele[3] * rez_pokusa[i, 2]
  63.                 + k.Alele[4] * Math.Pow(rez_pokusa[i, 0], 2)
  64.                 + k.Alele[5] * Math.Pow(rez_pokusa[i, 1], 2)
  65.                 + k.Alele[6] * Math.Pow(rez_pokusa[i, 2], 2)
  66.                 + k.Alele[7] * rez_pokusa[i, 0] * rez_pokusa[i, 1]
  67.                 + k.Alele[8] * rez_pokusa[i, 0] * rez_pokusa[i, 2]
  68.                 + k.Alele[9] * rez_pokusa[i, 1] * rez_pokusa[i, 2]
  69.                 + k.Alele[10] * rez_pokusa[i, 0] * rez_pokusa[i, 1] * rez_pokusa[i, 2];
  70.  
  71.             actual = rez_pokusa[i,3];
  72.             return guess;
  73.         }
  74.  
  75.         public int sampleCount {
  76.             get { return rez_pokusa.GetLength(0); }
  77.         }
  78.  
  79.  
  80.         // CM - removed constructor with "ensured diversity" which
  81.         // wasn't working anyhow
  82.  
  83.         // CM - calculate the raw and scaled fitness
  84.         public void RacunajFunkcijuFitnesa(List<Kromosom> kromosom)
  85.         {
  86.             //CM NOTE: bug? looks like this should be inside the k loop, since it's not,
  87.             //the value will likely grow VERY large, and 1/tempFitness will get smaller
  88.             // with every chromosome.
  89.             //
  90.             // NOTE: I removed the temporary list altogether to speed thingsup
  91.             //
  92.             //double tempFitnes = 0;
  93.  
  94.             for (int k = 0; k < kromosom.Count; k++)
  95.             {
  96.                 // CM initialize tempFitness to 0
  97.                 double sum_squares = 0;
  98.                 for (int i = 0; i < rez_pokusa.GetLength(0); i++) // for every sample point
  99.                 {
  100.                     // evaluate kromosome k against sample data point i
  101.                     double dummy;
  102.                     var guess = eval( kromosom[k], i, out dummy );
  103.  
  104.                     // CM - avoid the use of a temporary List<double>:
  105.                     sum_squares += Math.Pow (rez_pokusa[i,3]-guess,2); // least squares
  106.                 }
  107.  
  108.                 //
  109.                 // error = rez_pokusa - calc
  110.                 // tempFitnes = Sum(error^2)
  111.                 // tempFitness = sum of error^2 / count = average ( sum of error^2 )
  112.                 // kromosome fitness = 1/ average(sum of error^2)
  113.                 //
  114.  
  115.                 // CM -- track the RAW fitness values for logging, which
  116.                 // is the average sum of squared error
  117.                 kromosom[k].RawFitnes = sum_squares / rez_pokusa.Length;
  118.                
  119.                 // CM -- this is fitness scaling, which is inverting the raw fitness (least squares)                
  120.                 kromosom[k].ScaledFitness = 1 / kromosom[k].RawFitnes; // invert the fitness
  121.             }
  122.         }
  123.  
  124.         // CM - computes the normalized fitness
  125.         public void RacunajFunkcijuSelekcije(List<Kromosom> kromosom)
  126.         {
  127.             double tempFitnessAll = 0.0;
  128.             for (int k = 0; k < kromosom.Count; k++)
  129.             {
  130.                 tempFitnessAll += kromosom[k].NicheScaledFitness; // CM -- changed this to "active" fitness, which can be controlled by developer
  131.             }
  132.             // CM - normalize the fitness values
  133.             for (int k = 0; k < kromosom.Count; k++)
  134.             {
  135.                 kromosom[k].NormalizedFitness = kromosom[k].NicheScaledFitness / tempFitnessAll;
  136.             }
  137.  
  138.             // CM - sort by Normalized fitness, the normalized fitness
  139.             kromosom.Sort();
  140.         }
  141.  
  142.         // CM - added niching
  143.         //
  144.         public void Niching(List<Kromosom> kromosom, double max_stddev)
  145.         {
  146.             List<int> niches = new List<int>();
  147.  
  148.             // clear niches
  149.             foreach(var k in kromosom) {
  150.                 k.Niche = -1;
  151.             }
  152.  
  153.             // compute niches
  154.             for(int i = 0; i<kromosom.Count; i++ ) {
  155.                 var k = kromosom[i];
  156.  
  157.                 if(k.Niche != -1) continue; // already has a niche
  158.  
  159.                 k.Niche = niches.Count;
  160.                 int count = 1;
  161.                 for(int j=i+1; j<kromosom.Count; j++) {
  162.                     var kj = kromosom[j];
  163.                     double stddev = k.StdDev(kj);
  164.                     if(stddev < max_stddev) {
  165.                         kj.Niche = k.Niche;
  166.                         ++count;
  167.                     }
  168.                 }
  169.                 niches.Add(count);
  170.             }
  171.  
  172.             // calculate niche scaled fitness
  173.             foreach(var k in kromosom) {
  174.                 k.NicheScaledFitness = k.ScaledFitness / niches[k.Niche];
  175.             }
  176.         }
  177.  
  178.         // CM --
  179.         // 72% chance that this will pick the larger of the two items in the tourney
  180.         // 28% chance that the weaker survives
  181.         // Added two parameters: probablity that the fitter krom wins, and the number of individuals to return
  182.         public List<Kromosom> ProbabilisticBinaryTournamentSelection(List<Kromosom> kromosom, double prob, int N)
  183.         {
  184.             List<Kromosom> noviKromosom = new List<Kromosom>();
  185.             Kromosom veći, manji;
  186.             double probabilityOfTournament = prob, međa;
  187.             Kromosom kro1, kro2;
  188.             int pozicija_kro1, pozicija_kro2;
  189.            
  190.             while (noviKromosom.Count < N)
  191.             {
  192.                 pozicija_kro1 = random.Next(kromosom.Count);
  193.                 do{
  194.                     pozicija_kro2 = random.Next(kromosom.Count);
  195.                 }while(pozicija_kro1 == pozicija_kro2);
  196.                
  197.                 kro1 = kromosom[pozicija_kro1];
  198.                 kro2 = kromosom[pozicija_kro2];
  199.                
  200.                 međa= random.NextDouble(); // "border" ??? prob. threshold
  201.                 veći = kro1.NormalizedFitness >= kro2.NormalizedFitness ? kro1 : kro2; // larger
  202.                 manji = kro1.NormalizedFitness < kro2.NormalizedFitness ? kro1 : kro2; // smaller
  203.                
  204.                 if (međa < probabilityOfTournament)
  205.                     noviKromosom.Add(veći); // larger
  206.                 else
  207.                     noviKromosom.Add(manji); // smaller
  208.             }
  209.             return noviKromosom;
  210.         }
  211.  
  212.         // CM --
  213.         // in the style of your other routines
  214.         // Adding in a value for the number of items to select
  215.         public List<Kromosom> RouletteSelection(List<Kromosom> kromosom, int N)
  216.         {
  217.             var list = new List<Kromosom>();
  218.             for(int i=0; i<N; i++) {
  219.            
  220.                 double r = random.NextDouble();
  221.                 double sum = 0.0;
  222.                 foreach(var k in kromosom) {
  223.                     sum += k.NormalizedFitness;
  224.  
  225.                     if(r <= sum) {
  226.                         list.Add( k );
  227.                         break;
  228.                     }
  229.                 }
  230.             }
  231.  
  232.             return list;
  233.         }
  234.  
  235.         // CM - output of this will be N chromosomes that have had crossover
  236.         // applied, with a chance that no crossover has been appiled at all
  237.         //
  238.         // modification - removes elements from the input kromosom list
  239.         public List<Kromosom> Crossover_2(List<Kromosom> kromosom, int N)
  240.         {
  241.             int parent_1,parent_2;
  242.             Kromosom otac, majka; // father, mother
  243.             List<Kromosom> crossoverKromosom = new List<Kromosom>();
  244.             List<Kromosom> potomci = new List<Kromosom>();
  245.  
  246.             // CM - randomize the list (of tournament winners)
  247.             RazbacajListu(kromosom);
  248.  
  249.             int n = 0;
  250.             if(N == -1) N = kromosom.Count;
  251.  
  252.             while(n < N && kromosom.Count >= 2) {
  253.  
  254.                 // CM - the randomization here surely doesn't hurt, but it might
  255.                 // be a bit overkill. you've already randomized kromosom above,
  256.                 // and that list itself was randomized during the tournament.
  257.                 // not really a critical point, just thought I'd mention it
  258.                 // because it could improve your performance (you could just
  259.                 // pop two off the list, instead of calling List.Remove(Chromosome))
  260.  
  261.                 // just pop two off the front
  262.                 otac = kromosom[0];
  263.                 majka = kromosom[1];
  264.                 kromosom.RemoveRange(0,2);
  265.  
  266.                 // CM - "progeny" == Multiply(father,mother)
  267.                 potomci = Razmnozi(otac,majka);
  268.  
  269.                 crossoverKromosom.AddRange(potomci);
  270.  
  271.                 n += potomci.Count;
  272.             }
  273.            
  274.             return crossoverKromosom;
  275.         }
  276.  
  277.         // CM - "Multiply" ??? performs a crossover operation??
  278.         // and returns two children. Oh, I get it. Two parents mate
  279.         // and "multiply" to create offspring.
  280.         private List<Kromosom> Razmnozi(Kromosom otac, Kromosom majka)
  281.         {
  282.             double crossOverChance = random.NextDouble(); // CM - changed to double, allow different crossover techniques
  283.             List<Kromosom> potomci = new List<Kromosom>();
  284.             Kromosom sin = new Kromosom(otac.Alele);
  285.             Kromosom kćer = new Kromosom(majka.Alele);
  286.  
  287.             float SINGLE_XOVER_PROB = 0.88f;  // 88% chance of single xover
  288.             float EXTREME_XOVER_PROB = 0.98f; // 10% chance of extreme xover
  289.             //float NO_XOVER_PROB = 1.0f;  // 2% chance that nothing happens
  290.  
  291.             // CM note -- 8/12, 2/3, 66^% chance of a crossover
  292.             // CM change -- always perform crossovers
  293.             //if (crossOverChance < 8)
  294.             if (crossOverChance < SINGLE_XOVER_PROB)
  295.             {
  296.                 int loc = random.Next(otac.Alele.Count);
  297.  
  298.                 // swap only at a single location
  299.                 for(int i=loc; i<otac.Alele.Count; i++) {
  300.                     double temp = sin.Alele[i];
  301.                     sin.Alele[i] = kćer.Alele[i];
  302.                     kćer.Alele[i] = temp;
  303.                 }
  304.             }
  305.             else if (crossOverChance < EXTREME_XOVER_PROB)
  306.             {
  307.                 // son  
  308.                 // CM -- cleaned this up a bit, same functionality as before
  309.                 for (int i = 0; i < sin.Alele.Count; i++) {
  310.                     bool flip = random.Next(2) == 0;
  311.                     sin.Alele[i] = flip ? otac.Alele[i] : majka.Alele[i];
  312.                 }
  313.  
  314.                 // daughter
  315.                 for (int i = 0; i < kćer.Alele.Count; i++) {
  316.                     bool flip = random.Next(2) == 0;
  317.                     kćer.Alele[i] = flip ? majka.Alele[i] : otac.Alele[i];
  318.                 }
  319.             }
  320.  
  321.             potomci.Add(sin);
  322.             potomci.Add(kćer);
  323.             return potomci;
  324.         }
  325.  
  326.         // CM -- chose from several mutation algorithms, including
  327.         // no mutation at all
  328.         // N - number of elements to process, or -1 to process them all
  329.         public List<Kromosom> Mutation(List<Kromosom> kromosom, int N)
  330.         {
  331.             List<Kromosom> mutations =  new List<Kromosom>();
  332.  
  333.             float PROB_REPLACEMENT = 0.3f;
  334.             float PROB_SWAP = 0.6f;
  335.             float PROB_SCALE = 0.75f;
  336.             float PROB_SHIFT = 0.9f;
  337.             // 1.0f no change
  338.  
  339.             // process them all if N is -1
  340.             if (N == -1) N = kromosom.Count;
  341.  
  342.             for (int i=0; i<N && kromosom.Count > 0; i++)
  343.             {
  344.                 var k = new Kromosom( kromosom[0].Alele );
  345.                 kromosom.RemoveAt(0);
  346.                 mutations.Add( k );
  347.  
  348.                 // per-allele chance of mutation
  349.                 // mutate a single allele
  350.                 int j = random.Next( k.Alele.Count );
  351.  
  352.                 double tempMutation = random.NextDouble();
  353.  
  354.                 // CM -- this is pretty bold. really, very bold.
  355.                 //
  356.                 // There's a 30% chance of mutation
  357.                 // in the first 10 steps, and 5% chance of mutation after that?
  358.                 // You might want this to be more dynamic, say, based on the
  359.                 // variance of the population.
  360.                 //
  361.                 // And the 30% chance is a single-allele replacment, but
  362.                 // the 5% chance is a COMPLETELY NEW CHROMOSOME!
  363.                 //
  364.                 // CM -- changing this to pick a type of mutation
  365.                 if( tempMutation < PROB_REPLACEMENT) {
  366.                     // replace a value
  367.                     k.Alele[j] = random.NextDouble()*2000 - 1000;
  368.                 }
  369.                 else if (tempMutation < PROB_SWAP ) {
  370.                     // swap two values
  371.                     int j1 = j;
  372.                     int j2 = j1;
  373.                     while(j1 == j2) {
  374.                         j2 = random.Next( k.Alele.Count );
  375.                     }
  376.                     double v = k.Alele[j1];
  377.                     k.Alele[j1] = k.Alele[j2];
  378.                     k.Alele[j2] = v;
  379.                 }
  380.                 else if (tempMutation < PROB_SCALE) {
  381.                     // scale a value by a pct
  382.                     double scale = 0.8 + random.NextDouble()*0.4; // range 0.8 to 1.2
  383.                     k.Alele[ j ] *= scale;
  384.                 }
  385.                 else if (tempMutation < PROB_SHIFT) {
  386.                     // shift by some range
  387.                     double shift = -100 + random.NextDouble()*200; // +/- 100
  388.                     k.Alele[ j ] += shift;
  389.                 }
  390.             }
  391.  
  392.             return mutations;
  393.         }
  394.  
  395.         // CM - randomize the list of chromosomes
  396.         public void RazbacajListu(List<Kromosom> kromosom)
  397.         {
  398.             int n = kromosom.Count;
  399.            
  400.             while (n > 1)
  401.             {
  402.                 int k = (random.Next(0, n) % n);
  403.                 n--;
  404.                 Kromosom value = kromosom[k];
  405.                 kromosom[k] = kromosom[n];
  406.                 kromosom[n] = value;
  407.             }
  408.         }
  409.  
  410.         // CM - calculate population variance
  411.         public double RacunajVarijancu()
  412.         {
  413.             double meanOfThePopulation = 0.0;
  414.             for (int i = 0; i <kromosom.Count ; i++)
  415.             {
  416.                 meanOfThePopulation += kromosom[i].ScaledFitness;
  417.             }
  418.             meanOfThePopulation /= kromosom.Count;
  419.            
  420.             double zbrojKvadrataRazlika = 0.0;
  421.             for (int i = 0; i < kromosom.Count; i++)
  422.             {
  423.                 zbrojKvadrataRazlika += Math.Pow((kromosom[i].ScaledFitness-meanOfThePopulation),2);
  424.             }
  425.            
  426.             double varijance = zbrojKvadrataRazlika / kromosom.Count;
  427.             return varijance;
  428.         }
  429.  
  430.         // CM - Check Convergence
  431.         // najbolji = best
  432.         //
  433.         // This tests for convergence by seeing if the average fitness in the population
  434.         // is greater than 95% of the best fitness so far.
  435.         //
  436.         // This could abort VERY EARLY since most of the population in the beginning
  437.         // will have a VERY POOR FITNESS
  438.         public bool ProvjeriKonvergenciju(List<Kromosom> kromosom, Kromosom najbolji)
  439.         {
  440.             double avgFitnesSvih = 0.0;
  441.             foreach (var jedinka in kromosom)
  442.             {
  443.                 avgFitnesSvih += jedinka.ScaledFitness;
  444.             }
  445.             avgFitnesSvih /= kromosom.Count;
  446.            
  447.             if (avgFitnesSvih > najbolji.ScaledFitness * 0.95)
  448.                 return true;
  449.             else
  450.                 return false;
  451.         }
  452.     }
  453.    
  454. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement