Beispiel #1
0
        protected override IEnumerable <(IGene Root, string Origin)> GetVariations(IGene source)
        {
            if (Catalog.TryGetReduced(source, out var reduced))
            {
                yield return(reduced, "Reduction");
            }
            else
            {
                reduced = source;
            }

            foreach (var op in Open.Evaluation.Registry.Arithmetic.Functions)
            {
                yield return(Open.Evaluation.Registry.Arithmetic.GetFunction(Catalog, op, reduced), $"Root function ({op})");
            }

            var sourceTree      = Catalog.Factory.Map(source);
            var descendantNodes = sourceTree.GetDescendantsOfType().ToArray();
            var count           = descendantNodes.Length;

            int i;

            // Remove genes one at a time.
            for (i = 0; i < count; i++)
            {
                if (Catalog.Variation.TryRemoveValid(descendantNodes[i], out var pruned))
                {
                    yield return(pruned, "Remove descendant by index");
                }
            }

            // Strip down parameter levels to search for significance.
            var paramRemoved = sourceTree;

            while (true)
            {
                paramRemoved = paramRemoved.Clone();
                //var root = paramRemoved.Root;
                var paramGroups = paramRemoved.GetDescendantsOfType()
                                  .Where(n => n.Value is IParameter <double>)
                                  .GroupBy(n => ((IParameter <double>)n.Value).ID)
                                  .OrderByDescending(g => g.Key)
                                  .FirstOrDefault()?
                                  .Where(n => n.IsValidForRemoval())
                                  .ToArray();

                if (paramGroups == null || paramGroups.Length < 2)
                {
                    break;
                }

                foreach (var p in paramGroups)
                {
                    p.Parent.Remove(p);
                }

                yield return(
                    Catalog.FixHierarchy(paramRemoved).Recycle(),
                    "Parameter elimination");
            }

            for (i = 0; i < count; i++)
            {
                yield return(
                    Catalog.MultiplyNode(descendantNodes[i], -1),
                    "Invert descenant sign");
            }

            for (i = 0; i < count; i++)
            {
                yield return(
                    Catalog.AdjustNodeMultiple(descendantNodes[i], -1),
                    "Reduce descendant multiple");
            }

            for (i = 0; i < count; i++)
            {
                yield return(
                    Catalog.Variation.PromoteChildren(descendantNodes[i]),
                    "Promote descendant children");

                // Let mutation take care of this...
                // foreach (var fn in Operators.Available.Functions)
                // {
                //		yield return VariationCatalog.ApplyFunction(source, i, fn);
                // }
            }

            if (source is IParent)
            {
                var paramExpIncrease = Catalog.Variation.IncreaseParameterExponents(source);
                if (paramExpIncrease != source)
                {
                    yield return(paramExpIncrease,
                                 "Increase all parameter exponent");
                }
            }

            for (i = 0; i < count; i++)
            {
                yield return(
                    Catalog.AdjustNodeMultiple(descendantNodes[i], -1),
                    "Decrease descendant multiple");
            }

            for (i = 0; i < count; i++)
            {
                yield return(
                    Catalog.AdjustNodeMultiple(descendantNodes[i], +1),
                    "Increase descendant multiple");
            }

            for (i = 0; i < count; i++)
            {
                yield return(
                    Catalog.AddConstant(descendantNodes[i], 2),
                    "Add constant to descendant");                     // 2 ensures the constant isn't negated when adding to a product.
            }
            sourceTree.Recycle();
            if (!(reduced is Sum <double> sum))
            {
                yield break;
            }

            sourceTree = Catalog.Factory.Map(reduced);

            var clonedChildren = sourceTree.Children.Where(c => c.Value is IConstant <double>).ToArray();

            if (sourceTree.Count > clonedChildren.Length)
            {
                foreach (var c in clonedChildren)
                {
                    c.Detatch();
                }
            }

            var next = Catalog.FixHierarchy(sourceTree).Recycle();

            sourceTree.Recycle();
            yield return(Catalog.GetReduced(next), "Constants Stripped");

            if (sum.TryExtractGreatestFactor(Catalog, out var extracted, out _))
            {
                yield return(extracted, "GCF Extracted Reduction");
            }
        }