コード例 #1
0
        static double GetTreeOptimalByAscending(AndOrTree <int> tree, Func <int, int, int> comparer)
        {
            var nodeOptions = new int[tree.nodes.Length];

            for (int nodeIndex = tree.nodes.Length - 1; nodeIndex >= 0; nodeIndex--)
            {
                if (tree.nodes[nodeIndex].childrenIndices.Length == 0)
                {
                    nodeOptions[nodeIndex] = tree.nodes[nodeIndex].content;
                }
                else
                {
                    if (tree.nodes[nodeIndex].type == NodeType.AND)
                    {
                        nodeOptions[nodeIndex] = tree.nodes[nodeIndex].content +
                                                 tree.nodes[nodeIndex].childrenIndices
                                                 .Select(childIndex => nodeOptions[childIndex])
                                                 .Aggregate((result, item) => result + item);
                    }
                    else
                    {
                        nodeOptions[nodeIndex] = tree.nodes[nodeIndex].content +
                                                 tree.nodes[nodeIndex].childrenIndices
                                                 .Select(childIndex => nodeOptions[childIndex])
                                                 .Aggregate((result, item) => comparer(result, item));
                    }
                }
            }

            return(nodeOptions[0]);
        }
コード例 #2
0
        static AndOrTree <int> GetHardcodedTree()
        {
            var tree = new AndOrTree <int>();

            tree.nodes    = new AndOrTreeNode <int> [10];
            tree.nodes[0] = new AndOrTreeNode <int>(-4, new int[] { 1, 2, 3, 4 }, NodeType.OR);
            tree.nodes[1] = new AndOrTreeNode <int>(4, new int[] { 5, 6, 7, 8, 9 }, NodeType.AND);
            tree.nodes[2] = new AndOrTreeNode <int>(-8, new int[] {  }, NodeType.OR);
            tree.nodes[3] = new AndOrTreeNode <int>(-6, new int[] { }, NodeType.OR);
            tree.nodes[4] = new AndOrTreeNode <int>(7, new int[] { }, NodeType.OR);
            tree.nodes[5] = new AndOrTreeNode <int>(0, new int[] { }, NodeType.OR);
            tree.nodes[6] = new AndOrTreeNode <int>(6, new int[] { }, NodeType.OR);
            tree.nodes[7] = new AndOrTreeNode <int>(-1, new int[] { }, NodeType.OR);
            tree.nodes[8] = new AndOrTreeNode <int>(-4, new int[] { }, NodeType.OR);
            tree.nodes[9] = new AndOrTreeNode <int>(-9, new int[] { }, NodeType.OR);

            return(tree);
        }
コード例 #3
0
        public static AndOrTree <ContentType> GetRandomTree(
            int nodesAmount,
            int averageChildrenAmount,
            int childrenAmountRadius,
            Func <int, ContentType> contentGetter)
        {
            Random rnd = new Random();

            int nextChildIndex = 1;

            var tree = new AndOrTree <ContentType>();

            tree.nodes = new AndOrTreeNode <ContentType> [nodesAmount];

            for (int nodeIndex = 0; nodeIndex != tree.nodes.Length; nodeIndex++)
            {
                tree.nodes[nodeIndex]         = new AndOrTreeNode <ContentType>();
                tree.nodes[nodeIndex].content = contentGetter(nodeIndex);
                tree.nodes[nodeIndex].type    = rnd.Next(2) == 0 ? NodeType.AND : NodeType.OR;

                int childrenAmount = Math.Min(
                    rnd.Next(averageChildrenAmount - childrenAmountRadius, averageChildrenAmount + childrenAmountRadius + 1),
                    nodesAmount - nextChildIndex
                    );

                if (nextChildIndex + childrenAmount == nodesAmount - 1)
                {
                    childrenAmount++;
                }

                tree.nodes[nodeIndex].childrenIndices = new int[childrenAmount];
                for (int childIndex = 0; childIndex != tree.nodes[nodeIndex].childrenIndices.Length; childIndex++)
                {
                    if (nextChildIndex != nodesAmount)
                    {
                        tree.nodes[nodeIndex].childrenIndices[childIndex] = nextChildIndex++;
                    }
                }
            }

            return(tree);
        }
コード例 #4
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();
        }