Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 14873 was 14873, checked in by gkronber, 5 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: 7.5 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 HeuristicLab.Common;
26using HeuristicLab.Core;
27using HeuristicLab.Random;
28
29namespace HeuristicLab.ExpressionGenerator {
30  public abstract class ExpressionTemplate {
31    protected List<Tuple<Expression, double>> arguments;
32    protected readonly Func<IEnumerable<double>, double> transform;
33    public string Label { get; set; }
34
35    protected Expression Instantiate(string name, IRandom random, int n, bool sampleWithRepetition = false) {
36      var func = Expression.Function(name, transform, SampleArguments(random, n, sampleWithRepetition));
37      func.Label = Label;
38      return func;
39    }
40
41    protected IEnumerable<Expression> SampleArguments(IRandom random, int n, bool sampleWithRepetition = false) {
42      var weights = arguments.Select(x => x.Item2);
43      var args = sampleWithRepetition
44       ? arguments.SampleProportional(random, n, weights).Select(x => x.Item1)
45       : arguments.SampleProportionalWithoutRepetition(random, n, weights).Select(x => x.Item1);
46      return args;
47    }
48
49    public abstract Expression Instantiate(string name, IRandom random, bool sampleWithRepetition = false);
50
51    protected ExpressionTemplate(Func<IEnumerable<double>, double> transform) {
52      this.transform = transform;
53    }
54
55    public void AddArgument(Expression expression, double weight = 1d) {
56      arguments = arguments ?? new List<Tuple<Expression, double>>();
57      arguments.Add(Tuple.Create(expression, weight));
58    }
59
60    public void AddArguments(IEnumerable<Expression> expressions) {
61      arguments = arguments ?? new List<Tuple<Expression, double>>();
62      arguments.AddRange(expressions.Select(x => Tuple.Create(x, 1d)));
63    }
64
65    public void AddArguments(IEnumerable<Expression> expressions, IEnumerable<double> weights) {
66      arguments = arguments ?? new List<Tuple<Expression, double>>();
67      arguments.AddRange(expressions.Zip(weights, Tuple.Create));
68    }
69  }
70
71  public class RandomArityTemplate : ExpressionTemplate {
72    private readonly IRandom arityDistribution;
73
74    public RandomArityTemplate(Func<IEnumerable<double>, double> transform, IRandom arityDistribution) : base(transform) {
75      this.arityDistribution = arityDistribution;
76    }
77
78    public override Expression Instantiate(string name, IRandom random, bool sampleWithRepetition = false) {
79      var arity = (int)Math.Round(arityDistribution.NextDouble());
80      return Instantiate(name, random, arity, sampleWithRepetition);
81    }
82  }
83
84  public class FixedArityTemplate : ExpressionTemplate {
85    private readonly int arity;
86    public FixedArityTemplate(Func<IEnumerable<double>, double> transform, int arity) : base(transform) {
87      this.arity = arity;
88    }
89
90    public override Expression Instantiate(string name, IRandom random, bool sampleWithRepetition = false) {
91      return Instantiate(name, random, arity, sampleWithRepetition);
92    }
93  }
94
95  public class ScalingTemplate : ExpressionTemplate {
96    private readonly IRandom scaledVariance;
97    // w * expr
98    public ScalingTemplate(IRandom scaledVariance = null) : base(ExpressionGenerator.Product) {
99      this.scaledVariance = scaledVariance;
100    }
101
102    public override Expression Instantiate(string name, IRandom random, bool sampleWithRepetition = false) {
103      var expr = SampleArguments(random, 1, sampleWithRepetition).First();
104
105      // use the evaluator to determine variance of the sampled expression and initialize the constant accordingly to reach the target variance
106      var @const = 1.0;
107      if (scaledVariance != null) {
108        var evaluator = new ExpressionEvaluator();
109        var data = evaluator.GenerateData(expr, 10000);
110        var variance = data[expr].VariancePop();
111        @const = scaledVariance.NextDouble() / variance;
112      }
113
114      var func = Expression.Function(name, transform, new Expression[] { Expression.Constant(name, @const), expr });
115      func.Label = "*";
116      return func;
117    }
118  }
119
120  public class OffsetTemplate : ExpressionTemplate {
121    private readonly IRandom offset;
122    // expr + offset
123    public OffsetTemplate(IRandom offset = null) : base(ExpressionGenerator.Sum) {
124      this.offset = offset;
125    }
126
127    public override Expression Instantiate(string name, IRandom random, bool sampleWithRepetition = false) {
128      var expr = SampleArguments(random, 1, sampleWithRepetition).First();
129
130      // use the evaluator to determine variance of the sampled expression and initialize the constant accordingly to reach the target offset
131      var @const = 0.0;
132      if (offset != null) {
133        var evaluator = new ExpressionEvaluator();
134        var data = evaluator.GenerateData(expr, 10000);
135        var average = data[expr].Average();
136        @const = offset.NextDouble() - average;
137      }
138
139      var func = Expression.Function(name, transform, new Expression[] { Expression.Constant(name, @const), expr });
140      func.Label = "+";
141      return func;
142    }
143  }
144
145  public class RangeTemplate : ExpressionTemplate {
146    private readonly IRandom minValue;
147    private readonly IRandom valueRange;
148    // expr + offset
149    public RangeTemplate(IRandom minValue = null, IRandom valueRange = null) : base(null) {
150      this.minValue = minValue;
151      this.valueRange = valueRange;
152    }
153
154    public override Expression Instantiate(string name, IRandom random, bool sampleWithRepetition = false) {
155      var expr = SampleArguments(random, 1, sampleWithRepetition).First();
156
157      // use the evaluator to determine variance of the sampled expression and initialize the constant accordingly to reach the target offset
158      var mult = 1.0;
159      var add = 0.0;
160
161      if (minValue != null || valueRange != null) {
162        var evaluator = new ExpressionEvaluator();
163        var data = evaluator.GenerateData(expr, 10000);
164        if (valueRange != null) {
165          var targetRange = valueRange.NextDouble();
166          var min = data[expr].Min();
167          var max = data[expr].Max();
168          var range = max - min;
169          mult = targetRange / range;
170          add = -min + min / mult;
171        }
172        if (minValue != null) {
173          var targetMin = minValue.NextDouble();
174          var min = data[expr].Min();
175          add += (targetMin - min) / mult;
176        }
177
178        expr = Expression.Function(name + "-toZero", ExpressionGenerator.Sum, new Expression[] { Expression.Constant("name-add0", add), expr });
179        expr.Label = "+";
180        expr = Expression.Function(name + "-mult", ExpressionGenerator.Product, new Expression[] { Expression.Constant("name-mult", mult), expr });
181        expr.Label = "*";
182      }
183
184      return expr;
185    }
186  }
187}
Note: See TracBrowser for help on using the repository browser.