示例#1
0
        public void MathExpressionConverterThrowsArgumentException(string expression)
        {
            var mathExpressionConverter = new MathExpressionConverter();

            var result = new TestDelegate(()
                                          => mathExpressionConverter.Convert(0d, type, expression, cultureInfo));

            Assert.Throws <ArgumentException>(result);
        }
示例#2
0
        public void ShrinkMutationTest()
        {
            var converter = new MathExpressionConverter(MathPrimitiveSets.Default);
            var prog1     = converter.FromNormalNotation("((3*2)/2)");
            var prog2     = converter.FromNormalNotation("(4/2)");

            Console.WriteLine($"{prog1}, {prog2}");
            var op       = new ShrinkMutation <MathProgram, double>(ExtraPrimitiveSet);
            var allProgs = new HashSet <MathProgram>(op.GetAllMutations(prog1));

            Assert.IsTrue(allProgs.Contains(prog2), $"{prog2} should be a valid mutation of {prog1}.");
        }
示例#3
0
        public void ProgInAllMutationsTest()
        {
            var converter = new MathExpressionConverter(MathPrimitiveSets.Default);
            var prog1     = converter.FromPrefixNotation("(+ 2 1)");

            Console.WriteLine(prog1);
            foreach (var op in Operators)
            {
                var allProgs = new HashSet <MathProgram>(op.GetAllMutations(prog1));
                Assert.IsTrue(allProgs.Contains(prog1), $"{prog1} should be a valid mutation of {prog1}.");
            }
        }
示例#4
0
        public void PointMutationTest()
        {
            var converter = new MathExpressionConverter(MathPrimitiveSets.Default);
            var prog1     = converter.FromNormalNotation("1");
            var prog2     = converter.FromNormalNotation("4");

            Console.WriteLine($"{prog1}, {prog2}");
            var op       = new PointMutation <MathProgram, double>(ExtraPrimitiveSet);
            var allProgs = new HashSet <MathProgram>(op.GetAllMutations(prog1));

            Assert.IsTrue(allProgs.Contains(prog2), $"{prog2} should be a valid mutation of {prog1}.");
            Assert.AreEqual(allProgs.Count, 2, double.Epsilon, $"Mutation of {prog1} should only have 2 elements.");
        }
示例#5
0
        private static MathExpressionConverter GetConverter(out Variable xVar, out Variable yVar)
        {
            xVar = new Variable("x", new Range(-1, 1));
            yVar = new Variable("y", new Range(2, 4));
            var primitiveSet = new PrimitiveSet <MathProgram>(
                new List <Terminal> {
                xVar, yVar
            }, new MathProgram[0]);

            primitiveSet.Add(MathPrimitiveSets.Default);
            var converter = new MathExpressionConverter(primitiveSet);

            return(converter);
        }
示例#6
0
        public void NullParent2CrossoversTest()
        {
            var converter = new MathExpressionConverter(MathPrimitiveSets.Default);

            foreach (var op in Operators)
            {
                var prog2    = converter.FromNormalNotation("log(2,4)");
                var allProgs = new HashSet <MathProgram>(op.GetAllOffspring(null, prog2));
                var prog     = op.Crossover(null, prog2);
                Assert.IsNotNull(allProgs, "Crossover list of null should not be null.");
                Assert.AreEqual(allProgs.Count, 0, double.Epsilon, "Crossover list of null should be empty.");
                Assert.IsNull(prog, "Crossover of null should be null.");
            }
        }
示例#7
0
        public void Parent2InAllCrossoversTest()
        {
            var converter = new MathExpressionConverter(MathPrimitiveSets.Default);
            var prog1     = converter.FromPrefixNotation("(- (+ 2 1) 3)");
            var prog2     = converter.FromPrefixNotation("(/ (+ (cos 3) 1) 2)");

            Console.WriteLine($"{prog1}, {prog2}");
            foreach (var op in Operators)
            {
                var allProgs = new HashSet <MathProgram>(op.GetAllOffspring(prog1, prog2));
                Assert.IsTrue(allProgs.Contains(prog2),
                              $"{prog2} should be a valid crossover between {prog1} and {prog2}.");
            }
        }
示例#8
0
        public void MutationsInAllStochasticMutationTest()
        {
            var converter = new MathExpressionConverter(MathPrimitiveSets.Default);
            var mut       = new StochasticMutation <MathProgram>(Operators);
            var prog1     = converter.FromPrefixNotation("(* 2 (^ 1 4))");
            var allMuts   = new HashSet <MathProgram>(mut.GetAllMutations(prog1));

            Console.WriteLine(prog1);
            foreach (var op in Operators)
            {
                var prog = op.Mutate(prog1);
                Console.WriteLine(prog);
                Assert.IsTrue(allMuts.Contains(prog), $"{prog} should be a valid mutation of {prog1}.");
            }
        }
示例#9
0
        public void AllOnePointInAllUniformCrossoverTest()
        {
            var converter = new MathExpressionConverter(MathPrimitiveSets.Default);
            var prog1     = converter.FromPrefixNotation("(- (+ 2 1) 3)");
            var prog2     = converter.FromPrefixNotation("(/ (+ (cos 3) 1) 2)");

            Console.WriteLine($"{prog1}, {prog2}");
            var allOnePointProgs =
                new HashSet <MathProgram>(new OnePointCrossover <MathProgram, double>().GetAllOffspring(prog1, prog2));
            var allUniformProgs =
                new HashSet <MathProgram>(new UniformCrossover <MathProgram, double>().GetAllOffspring(prog1, prog2));

            Assert.IsTrue(allOnePointProgs.IsSubsetOf(allUniformProgs),
                          $"All one-point crossovers between {prog1} and {prog2} should be included in all uniform crossovers.");
        }
        /// <inheritdoc />
        public double Calculate(MathProgram prog1, MathProgram prog2)
        {
            if (prog1 == null || prog2 == null)
            {
                return(0);
            }
            if (prog1.Equals(prog2))
            {
                return(1);
            }

            var expr1 = MathExpressionConverter.ToPrefixNotationExpression(prog1);
            var expr2 = MathExpressionConverter.ToPrefixNotationExpression(prog2);

            return(1d - (double)expr1.LevenshteinDistance(expr2) / Math.Max(expr1.Length, expr2.Length));
        }
示例#11
0
        public void MathExpressionConverter_ReturnsCorrectResult(
            string expression, double x, double expectedResult)
        {
            var mathExpressionConverter = new MathExpressionConverter();

            var result = mathExpressionConverter.Convert(x, type, expression, cultureInfo);

            if (result == null)
            {
                Assert.Fail();
            }
            else
            {
                Assert.IsTrue(Math.Abs((double)result - expectedResult) < tolerance);
            }
        }
        public void Sin()
        {
            var converter = new MathExpressionConverter()
            {
                ConvertExpression     = "Sin(x)",
                ConvertBackExpression = "Asin(x)"
            };
            var r = new Random();

            for (int i = 0; i < 100; i++)
            {
                var d = r.NextDouble();
                Assert.AreEqual(Math.Sin(d), (double)converter.Convert(d, typeof(double), null, null), 0.00001);
                Assert.AreEqual(d, (double)converter.ConvertBack(Math.Sin(d), typeof(double), null, null), 0.00001);
            }
        }
        public void Square()
        {
            var converter = new MathExpressionConverter()
            {
                ConvertExpression     = "x^2",
                ConvertBackExpression = "Sqrt(x)"
            };
            var r = new Random();

            for (int i = 0; i < 100; i++)
            {
                var d = r.NextDouble() * 100;
                Assert.AreEqual(d * d, (double)converter.Convert(d, typeof(double), null, null), 0.00001);
                Assert.AreEqual(d, (double)converter.ConvertBack(d * d, typeof(double), null, null), 0.00001);
            }
        }
示例#14
0
 internal ProgramInfo(MathExpressionConverter converter, MathProgram program)
 {
     this.NormalExpression = converter.ToNormalNotation(program);
     this.PrefixExpression = converter.ToPrefixNotation(program);
     this.Length           = program.Length;
     this.Breadth          = program.GetMaxBreadth();
     this.Depth            = program.GetMaxDepth();
     this.SubPrograms      = program.GetSubPrograms()
                             .Select(subProg => converter.ToNormalNotation((MathProgram)subProg)).ToList();
     this.SubCombinations = program.GetSubCombinations()
                            .Select(subProg => converter.ToNormalNotation((MathProgram)subProg)).ToList();
     this.Leaves = program.GetLeaves()
                   .ToDictionary(leaf => converter.ToNormalNotation((MathProgram)leaf.Key), count => count.Value);
     this.Primitives = program.GetPrimitives()
                       .ToDictionary(primitive => primitive.Key.Label, count => count.Value);
 }
示例#15
0
        public MainForm()
        {
            this.InitializeComponent();

            // creates primitives
            var terminals = new List <MathProgram>();

            for (var c = 'a'; c <= 'z'; c++)
            {
                terminals.Add(new Variable(c.ToString()));
            }
            var primitives = new PrimitiveSet <MathProgram>(terminals, MathPrimitiveSets.Default.Functions);

            // creates converter
            this._converter = new MathExpressionConverter(primitives);
        }
示例#16
0
        public void SimplifyMutationTest()
        {
            var converter = new MathExpressionConverter(MathPrimitiveSets.Default);
            var prog1     = converter.FromNormalNotation("((2/1)-3)");
            var prog2     = converter.FromNormalNotation("-1");

            Console.WriteLine($"{prog1}, {prog2}");
            var op       = new SimplifyMutation();
            var allProgs = new HashSet <MathProgram>(op.GetAllMutations(prog1));

            foreach (var mut in allProgs)
            {
                Console.WriteLine($"\t{mut}");
            }
            Assert.IsTrue(allProgs.Contains(prog1), $"{prog2} should be a valid mutation of {prog1}.");
            Assert.IsTrue(allProgs.Contains(prog2), $"{prog2} should be a valid mutation of {prog1}.");
            Assert.AreEqual(allProgs.Count, 3, double.Epsilon, $"Mutation of {prog1} should only have 3 elements.");
        }
示例#17
0
        public void NoContextCrossoverTest()
        {
            var converter = new MathExpressionConverter(MathPrimitiveSets.Default);
            var prog1     = converter.FromNormalNotation("0");
            var prog2     = converter.FromNormalNotation("((2+3)-1)");

            Console.WriteLine($"{prog1}, {prog2}");
            var op       = new ContextPreservingCrossover <MathProgram, double>();
            var allProgs = new HashSet <MathProgram>(op.GetAllOffspring(prog1, prog2));
            var prog     = op.Crossover(prog1, prog2);

            Assert.IsTrue(allProgs.Contains(prog2),
                          $"{prog} should be a valid crossover between {prog1} and {prog2}.");
            Assert.IsTrue(prog.Equals(prog2),
                          $"{prog} should be the only valid crossover between {prog1} and {prog2}.");
            Assert.AreEqual(allProgs.Count, 1, double.Epsilon,
                            $"Crossover between {prog1} and {prog2} should only have 1 element.");
        }
示例#18
0
        public void EqualCrossoversTest()
        {
            var converter = new MathExpressionConverter(MathPrimitiveSets.Default);
            var prog1     = converter.FromNormalNotation("((2+3)-1)");
            var prog2     = converter.FromNormalNotation("((3+2)-1)");

            Console.WriteLine($"{prog1}, {prog2}");
            foreach (var op in Operators)
            {
                var allProgs = new HashSet <MathProgram>(op.GetAllOffspring(prog1, prog2));
                Assert.IsTrue(allProgs.Contains(prog1),
                              $"{prog1} should be a valid crossover between {prog1} and {prog2}.");
                Assert.IsTrue(allProgs.Contains(prog2),
                              $"{prog1} should be a valid crossover between {prog1} and {prog2}.");
                Assert.AreEqual(allProgs.Count, 1, double.Epsilon,
                                $"Crossover between {prog1} and {prog2} should only have 1 element.");
            }
        }
示例#19
0
        private static MathProgram CreateProgram()
        {
            var a        = new Variable("a");
            var b        = new Variable("b");
            var c        = new Variable("c");
            var d        = new Variable("d");
            var e        = new Variable("e");
            var addition = new AdditionFunction(a, a);
            var subtr    = new SubtractionFunction(a, a);

            var primitives = new PrimitiveSet <MathProgram>(
                new HashSet <Terminal> {
                a, b, c, d, e
            },
                new HashSet <MathProgram> {
                addition, subtr
            });

            var converter = new MathExpressionConverter(primitives);

            return(converter.FromPrefixNotation("(+ (- a b) (- c (+ d e)))"));
        }
示例#20
0
        public static void Main(string[] args)
        {
            const uint   popSize          = 200;
            const uint   maxDepth         = 4;
            const uint   maxGenerations   = 2000;
            const uint   maxElementLength = 20;
            const uint   maxNoImproveGen  = (uint)(maxGenerations * 0.5);
            const string solutionExp      = "(+ (+ x x) (+ (* 3 (* x x)) 1))";

            var variable = new Variable("x");

            var primitives = new PrimitiveSet <MathProgram>(
                new HashSet <Terminal> {
                variable, new Constant(0), new Constant(1), new Constant(3)
            },
                new HashSet <MathProgram>());

            primitives.Add(MathPrimitiveSets.Default);

            var fitnessFunction = new FitnessFunction(x => 2 * x + 3 * x * x + 1, variable, 100, -50, 50);

            var solution = new MathExpressionConverter(primitives).FromPrefixNotation(solutionExp);

            Console.WriteLine("===================================");
            Console.WriteLine("Fitness: {0} | {1}", fitnessFunction.Evaluate(solution), solution);
            solution.ToGraphvizFile(Path.GetFullPath("."), "solution", GraphvizImageType.Png);
            Console.WriteLine("===================================");

            var seed = new AdditionFunction(new Constant(1), variable);

            var elementGenerator =
                new StochasticProgramGenerator <MathProgram, double>(
                    new List <IProgramGenerator <MathProgram, double> >
            {
                new GrowProgramGenerator <MathProgram, double>(),
                new FullProgramGenerator <MathProgram, double>()
            });
            var selection = new TournamentSelection <MathProgram>(fitnessFunction, (uint)(popSize * 0.05));
            var crossover = new StochasticCrossover <MathProgram>(
                new List <ICrossoverOperator <MathProgram> >
            {
                new SubtreeCrossover <MathProgram, double>(),
                new OnePointCrossover <MathProgram, double>(),
                new ContextPreservingCrossover <MathProgram, double>(),
                new UniformCrossover <MathProgram, double>()
            });
            var mutation = new StochasticMutation <MathProgram>(
                new List <IMutationOperator <MathProgram> >
            {
                new SubtreeMutation <MathProgram, double>(elementGenerator, primitives, 1),
                new PointMutation <MathProgram, double>(primitives),

                //new ShrinkMutation(primitives),
                new SimplifyMutation(),
                new HoistMutation <MathProgram, double>()
            });

            var pop = new Population <MathProgram, double>(
                popSize, primitives, elementGenerator,
                fitnessFunction, selection, crossover, mutation, maxDepth, maxElementLength);

            pop.Init(new HashSet <MathProgram> {
                seed
            });

            MathProgram best             = null;
            var         numNoImproveGens = -1;

            for (var i = 0u; i < maxGenerations && numNoImproveGens < maxNoImproveGen; i++)
            {
                pop.Step();

                var newBest = pop.BestProgram;
                if (best == null)
                {
                    best = newBest;
                }
                var diff = fitnessFunction.Evaluate(newBest) - fitnessFunction.Evaluate(best);
                numNoImproveGens = diff.Equals(0) && best.Equals(newBest) ? numNoImproveGens + 1 : 0;
                best             = newBest;

                Print(pop, i, fitnessFunction, diff);
            }

            best.ToGraphvizFile(Path.GetFullPath("."), "best", GraphvizImageType.Png);
            Console.WriteLine("===================================");
            Console.WriteLine($"Best: {pop.BestProgram}, fitness: {fitnessFunction.Evaluate(pop.BestProgram):0.000}");
            Console.ReadKey();
        }