Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.ExpressionGenerator/HeuristicLab.ExpressionGenerator/3.4/ExpressionGenerator.cs @ 14873

Last change on this file since 14873 was 14873, checked in by gkronber, 7 years ago

#2704: added possibility to automatically adjust constants based on the distributions of evaluated expressions to allow limiting distributions for arguments of functions (e.g. log should have positive args only, exp should have rather small args only)

File size: 8.7 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2016 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections.Generic;
24using System.Linq;
25using System.Runtime.InteropServices;
26using HeuristicLab.Common;
27using HeuristicLab.Core;
28using HeuristicLab.Random;
29
30namespace HeuristicLab.ExpressionGenerator {
31  public static class ExpressionGenerator {
32    public static IEnumerable<Expression> GenerateRandomDistributedVariables(int numberOfVariables, string variablePrefix, IRandom randomDistribution) {
33      return Enumerable.Range(1, numberOfVariables).Select(x => Expression.RandomVariable(string.Format("{0}{1}", variablePrefix, x), randomDistribution));
34    }
35
36    public static Expression NonlinearExpression(IRandom uniformRandom, Expression[] variables, bool useLog, bool useExp) {
37      var scalingTemplate = ScaledExpression(uniformRandom, variables, varianceRandom: new UniformDistributedRandom(uniformRandom, 1, 10));
38      var scaledVars = Instantiate(scalingTemplate, uniformRandom, 100, "scaledVar");
39
40      var sumTemplate = new RandomArityTemplate(Sum, new UniformDistributedRandom(uniformRandom, 1, 3)) { Label = "+" };
41      sumTemplate.AddArguments(scaledVars);
42      var prodTemplate = new RandomArityTemplate(Product, new UniformDistributedRandom(uniformRandom, 1, 3)) { Label = "*" };
43      prodTemplate.AddArguments(variables);
44
45      var logTemplate = LogOfScaledExpression(uniformRandom, Instantiate(sumTemplate, uniformRandom, 100, "sumOfScaledVars"),
46        minValue: new UniformDistributedRandom(uniformRandom, 0.1, 2),
47        valueRange: new UniformDistributedRandom(uniformRandom, 1, 10));
48
49      var expTemplate = ExpOfScaledExpression(uniformRandom, Instantiate(prodTemplate, uniformRandom, 100, "prodOfVars"),
50        valueRange: new UniformDistributedRandom(uniformRandom, 1, 4)); // TODO should also specify an offset
51
52      var scaledExprTemplate = new ScalingTemplate(new UniformDistributedRandom(uniformRandom, 1, 10)) { Label = "*" };
53      if (useLog) scaledExprTemplate.AddArguments(Instantiate(logTemplate, uniformRandom, 100, "log"));
54      if (useExp) scaledExprTemplate.AddArguments(Instantiate(expTemplate, uniformRandom, 100, "exp"));
55
56      var mainTemplate = new RandomArityTemplate(Sum, new UniformDistributedRandom(uniformRandom, 3, 5));
57      mainTemplate.AddArguments(scaledVars);
58      if (useLog || useExp) {
59        mainTemplate.AddArguments(Instantiate(scaledExprTemplate, uniformRandom, 100, "scaledExpr"));
60      }
61      mainTemplate.Label = "+";
62
63      return mainTemplate.Instantiate("main", uniformRandom, false);
64    }
65
66    public static Expression Polynomial(IRandom uniformRandom, Expression[] variables, bool useLog, bool useExp) {
67      const int count = 10; // how many instances of each template should be produce?
68      int i = 1;
69      // the main template
70      var template = new RandomArityTemplate(Sum, new UniformDistributedRandom(uniformRandom, 2, count)) { Label = "+" };
71      template.AddArguments(variables);
72
73      var sumTemplate = new RandomArityTemplate(Sum, new UniformDistributedRandom(uniformRandom, 1, variables.Length)) { Label = "+" };
74      sumTemplate.AddArguments(variables);
75
76      var productTemplate = new RandomArityTemplate(Product, new UniformDistributedRandom(uniformRandom, 1, variables.Length)) { Label = "*" };
77      productTemplate.AddArguments(variables);
78
79      var inverseTemplate = new FixedArityTemplate(Division, 1) { Label = "/" };
80      inverseTemplate.AddArguments(variables);
81      inverseTemplate.AddArguments(Enumerable.Range(1, count).Select(x => sumTemplate.Instantiate(string.Format("sum{0}", i++), uniformRandom)));
82      inverseTemplate.AddArguments(Enumerable.Range(1, count).Select(x => productTemplate.Instantiate(string.Format("prod{0}", i++), uniformRandom)));
83
84      if (useLog) {
85        var logTemplate = new FixedArityTemplate(Log, 1) { Label = "log" };
86        logTemplate.AddArguments(variables);
87        logTemplate.AddArguments(Enumerable.Range(1, count).Select(x => sumTemplate.Instantiate(string.Format("sum{0}", i++), uniformRandom)));
88        template.AddArguments(Enumerable.Range(1, count).Select(x => logTemplate.Instantiate(string.Format("log{0}", i++), uniformRandom)));
89        inverseTemplate.AddArguments(Enumerable.Range(1, count).Select(x => logTemplate.Instantiate(string.Format("log{0}", i++), uniformRandom)));
90      }
91
92      if (useExp) {
93        var expTemplate = new FixedArityTemplate(Exp, 1) { Label = "exp" };
94        expTemplate.AddArguments(variables);
95        expTemplate.AddArguments(Enumerable.Range(1, count).Select(x => productTemplate.Instantiate(string.Format("prod{0}", i++), uniformRandom)));
96        template.AddArguments(Enumerable.Range(1, count).Select(x => expTemplate.Instantiate(string.Format("exp{0}", i++), uniformRandom)));
97        inverseTemplate.AddArguments(Enumerable.Range(1, count).Select(x => expTemplate.Instantiate(string.Format("exp{0}", i++), uniformRandom)));
98      }
99
100      template.AddArguments(Enumerable.Range(1, count).Select(x => inverseTemplate.Instantiate(string.Format("inv{0}", i++), uniformRandom)));
101      return template.Instantiate("polynomial", uniformRandom);
102    }
103
104    // variance random must have support only positive numbers
105    private static ExpressionTemplate ScaledExpression(IRandom uniformRandom, IEnumerable<Expression> arguments, IRandom varianceRandom) {
106      var scalingTemplate = new ScalingTemplate(scaledVariance: varianceRandom);
107      scalingTemplate.AddArguments(arguments);
108      scalingTemplate.Label = "*";
109      return scalingTemplate;
110    }
111
112    /// template scales and translates the argument expression first to guarantee positive values
113    private static ExpressionTemplate LogOfScaledExpression(IRandom uniformRandom, IEnumerable<Expression> arguments,
114      IRandom minValue = null, IRandom valueRange = null) {
115      var limitToRangeTemplate = new RangeTemplate(minValue, valueRange);
116      limitToRangeTemplate.AddArguments(arguments);
117
118      var logTemplate = new FixedArityTemplate(Log, 1) { Label = "log" };
119      logTemplate.AddArguments(Enumerable.Range(1, 100).Select(i => limitToRangeTemplate.Instantiate(string.Format("log{0}", i), uniformRandom, false)));
120      return logTemplate;
121    }
122
123    /// template scales the argument expression first to guarantee reasonable values
124    private static ExpressionTemplate ExpOfScaledExpression(IRandom uniformRandom, IEnumerable<Expression> arguments,
125      IRandom valueRange = null) {
126      var limitToRangeTemplate = new RangeTemplate(null, valueRange);
127      limitToRangeTemplate.AddArguments(arguments);
128
129      var expTemplate = new FixedArityTemplate(Exp, 1) { Label = "exp" };
130      expTemplate.AddArguments(Enumerable.Range(1, 100).Select(i => limitToRangeTemplate.Instantiate(string.Format("exp{0}", i), uniformRandom, false)));
131      return expTemplate;
132    }
133
134    public static IEnumerable<Expression> Instantiate(ExpressionTemplate template, IRandom random, int count, string name) {
135      return Enumerable.Range(1, count).Select(i => template.Instantiate(name + i, random, false));
136    }
137
138    #region static functions
139    public static double Sum(IEnumerable<double> args) {
140      return args.Sum();
141    }
142
143    public static double Product(IEnumerable<double> args) {
144      return args.Aggregate((x, y) => x * y);
145    }
146
147    public static double Division(IEnumerable<double> args) {
148      if (args.Count() == 1)
149        return 1 / args.First();
150
151      return args.Aggregate((x, y) => x / y);
152    }
153
154    public static double Subtraction(IEnumerable<double> args) {
155      if (args.Count() == 1)
156        return -args.First();
157
158      return args.Aggregate((x, y) => x - y);
159    }
160
161    public static double Exp(IEnumerable<double> args) {
162      return Math.Exp(args.Single());
163    }
164
165    public static double Log(IEnumerable<double> args) {
166      return Math.Log(args.Single());
167    }
168
169    public static double Square(IEnumerable<double> args) {
170      var v = args.Single();
171      return v * v;
172    }
173    #endregion
174  }
175}
Note: See TracBrowser for help on using the repository browser.