Beispiel #1
0
        static void Main(string[] args)
        {
            Random rnd = new Random();

            var tree = AndOrTree <int> .GetRandomTree(100000, 5, 2, index => rnd.Next(-10, 11));

            var treeMax = GetTreeOptimalByAscending(tree, Math.Max);

            var treeMin = GetTreeOptimalByAscending(tree, Math.Min);

            var orNodeIndices = tree.GetOrNodeIndices();

            int orNodesAmount = orNodeIndices.Count;

            var orNodeOptionMax = new Dictionary <int, int>();

            Func <Dictionary <int, int>, double> fitness1 = (Dictionary <int, int> gen) =>
            {
                var structure = new List <int>();
                var queue     = new Queue <int>();
                queue.Enqueue(0);
                while (queue.Count > 0)
                {
                    int currentNode = queue.Dequeue();
                    structure.Add(currentNode);
                    if (tree.nodes[currentNode].childrenIndices.Length > 0)
                    {
                        if (tree.nodes[currentNode].type == NodeType.AND)
                        {
                            foreach (var childIndex in tree.nodes[currentNode].childrenIndices)
                            {
                                queue.Enqueue(childIndex);
                            }
                        }
                        else
                        {
                            queue.Enqueue(tree.nodes[currentNode].childrenIndices[gen[currentNode]]);
                        }
                    }
                }
                return(structure.Aggregate(0, (sum, node) => sum + tree.nodes[node].content));
            };

            Func <Dictionary <int, int> > generate1 = () =>
            {
                var gen = new Dictionary <int, int>();
                orNodeIndices.ForEach(index => gen.Add(index, rnd.Next(tree.nodes[index].childrenIndices.Length)));
                return(gen);
            };

            Func <Dictionary <int, int>, Dictionary <int, int>, Dictionary <int, int> > cross1 = (Dictionary <int, int> gen1, Dictionary <int, int> gen2) =>
            {
                var gen = new Dictionary <int, int>();

                for (int i = 0; i != orNodesAmount; i++)
                {
                    int key = orNodeIndices[i];
                    gen.Add(key, rnd.Next(2) == 0 ? gen1[key] : gen2[key]);
                }

                return(gen);
            };

            Action <Dictionary <int, int> > mutate1 = (Dictionary <int, int> sourceGen) =>
            {
                int[] keys = sourceGen.Keys.ToArray();

                for (int i = 0; i != orNodesAmount; i++)
                {
                    if (rnd.Next(10) > 8)
                    {
                        int key = keys[i];
                        sourceGen[key] = rnd.Next(tree.nodes[key].childrenIndices.Length);
                    }
                }
            };

            double scope = treeMax - treeMin;

            Func <double, bool> stop1 = (double result) =>
            {
                return((treeMax - result) / scope < 0.05);
            };

            Action <int, double, List <Dictionary <int, int> > > logger1 = (int generationNumber, double result, List <Dictionary <int, int> > generation) =>
            {
                var mistake = (treeMax - result) / scope;

                var evaluations = generation.Select(gen => fitness1(gen)).ToList();

                int    segmentAmount = 10;
                double segmentSize   = (treeMax - treeMin) / segmentAmount;
                string info          = "";

                var histogram = new List <double>();


                for (int i = 0; i != segmentAmount; i++)
                {
                    var begin = treeMin + segmentSize * i;
                    var end   = begin + segmentSize + ((i == segmentAmount - 1) ? 1 : 0);

                    histogram.Add(Math.Round((double)evaluations.Where(e => e >= begin && e < end).Count() / evaluations.Count() * 10000) / 100);

                    info += histogram.Last() + "% ";
                }

                var sum = Math.Round(histogram.Sum() * 10000) / 10000;

                info += $" (sum is {sum}) ";

                Console.WriteLine($"{generationNumber}:  {info}->  {Convert.ToInt32(mistake * 100)}%");
            };

            var geneticSolver = new GeneticSolver <Dictionary <int, int> >(fitness1, generate1, cross1, mutate1, stop1, logger1);

            var gen = geneticSolver.Solve(10000, 1, (Dictionary <int, int> source) => new Dictionary <int, int>(source));

            var result = fitness1(gen);

            Console.WriteLine("Result: " + result);
            Console.WriteLine("Best: " + treeMax);
            Console.WriteLine("Worst: " + treeMin);

            double mistake = (treeMax - result) / scope;

            Console.WriteLine("Mistake: " + Convert.ToInt32(mistake * 100) + "%");

            Console.ReadKey();
        }