Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 14880 was 14880, checked in by gkronber, 5 years ago

#2704: added more expression templates

File size: 10.6 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.ExpressionGenerator.Interfaces;
28using HeuristicLab.Random;
29
30namespace HeuristicLab.ExpressionGenerator {
31  public interface IExpressionTemplate {
32    string Label { get; set; }
33  }
34  public abstract class ExpressionTemplate : IExpressionTemplate {
35    protected List<Tuple<Expression, double>> arguments;
36    protected readonly Func<IEnumerable<double>, double> transform;
37    public string Label { get; set; }
38
39    protected Expression Instantiate(string name, IRandom random, int n, bool sampleWithRepetition = false) {
40      var func = Expression.Function(name, transform, SampleArguments(random, n, sampleWithRepetition));
41      func.Label = Label;
42      return func;
43    }
44
45    protected IEnumerable<Expression> SampleArguments(IRandom random, int n, bool sampleWithRepetition = false) {
46      var weights = arguments.Select(x => x.Item2);
47      var args = sampleWithRepetition
48       ? arguments.SampleProportional(random, n, weights, windowing: false).Select(x => x.Item1)
49       : arguments.SampleProportionalWithoutRepetition(random, n, weights, windowing: false).Select(x => x.Item1);
50      return args;
51    }
52
53    public abstract Expression Instantiate(string name, IRandom random, bool sampleWithRepetition = false);
54
55    protected ExpressionTemplate(Func<IEnumerable<double>, double> transform) {
56      this.transform = transform;
57    }
58
59    public void AddArgument(Expression expression, double weight = 1d) {
60      arguments = arguments ?? new List<Tuple<Expression, double>>();
61      arguments.Add(Tuple.Create(expression, weight));
62    }
63
64    public void AddArguments(IEnumerable<Expression> expressions) {
65      arguments = arguments ?? new List<Tuple<Expression, double>>();
66      arguments.AddRange(expressions.Select(x => Tuple.Create(x, 1d)));
67    }
68
69    public void AddArguments(IEnumerable<Expression> expressions, IEnumerable<double> weights) {
70      arguments = arguments ?? new List<Tuple<Expression, double>>();
71      arguments.AddRange(expressions.Zip(weights, Tuple.Create));
72    }
73  }
74
75  public class RandomArityTemplate : ExpressionTemplate {
76    private readonly IDistribution<int> arityDistribution;
77
78    public RandomArityTemplate(Func<IEnumerable<double>, double> transform, IDistribution<int> arityDistribution) : base(transform) {
79      this.arityDistribution = arityDistribution;
80    }
81
82    public override Expression Instantiate(string name, IRandom random, bool sampleWithRepetition = false) {
83      var arity = arityDistribution.Sample();
84      return Instantiate(name, random, arity, sampleWithRepetition);
85    }
86  }
87
88  public class FixedArityTemplate : ExpressionTemplate {
89    private readonly int arity;
90    public FixedArityTemplate(Func<IEnumerable<double>, double> transform, int arity) : base(transform) {
91      this.arity = arity;
92    }
93
94    public override Expression Instantiate(string name, IRandom random, bool sampleWithRepetition = false) {
95      return Instantiate(name, random, arity, sampleWithRepetition);
96    }
97  }
98
99
100  public class BinaryOperatorTemplate : IExpressionTemplate {
101    public string Label { get; set; }
102    private readonly Func<IEnumerable<double>, double> transform;
103    private List<Tuple<Expression, double>> leftArguments;
104    private List<Tuple<Expression, double>> rightArguments;
105
106    public BinaryOperatorTemplate(Func<IEnumerable<double>, double> transform) {
107      this.transform = transform;
108    }
109
110    public void AddLeftArgument(Expression expression, double weight = 1d) {
111      leftArguments = leftArguments ?? new List<Tuple<Expression, double>>();
112      leftArguments.Add(Tuple.Create(expression, weight));
113    }
114
115    public void AddLeftArguments(IEnumerable<Expression> expressions) {
116      leftArguments = leftArguments ?? new List<Tuple<Expression, double>>();
117      leftArguments.AddRange(expressions.Select(x => Tuple.Create(x, 1d)));
118    }
119
120    public void AddLeftArguments(IEnumerable<Expression> expressions, IEnumerable<double> weights) {
121      leftArguments = leftArguments ?? new List<Tuple<Expression, double>>();
122      leftArguments.AddRange(expressions.Zip(weights, Tuple.Create));
123    }
124
125
126    public void AddRightArgument(Expression expression, double weight = 1d) {
127      rightArguments = rightArguments ?? new List<Tuple<Expression, double>>();
128      rightArguments.Add(Tuple.Create(expression, weight));
129    }
130
131    public void AddRightArguments(IEnumerable<Expression> expressions) {
132      rightArguments = rightArguments ?? new List<Tuple<Expression, double>>();
133      rightArguments.AddRange(expressions.Select(x => Tuple.Create(x, 1d)));
134    }
135
136    public void AddRightArguments(IEnumerable<Expression> expressions, IEnumerable<double> weights) {
137      rightArguments = rightArguments ?? new List<Tuple<Expression, double>>();
138      rightArguments.AddRange(expressions.Zip(weights, Tuple.Create));
139    }
140
141    public Expression Instantiate(string name, IRandom random, bool sampleWithRepetition = false) {
142      Expression leftArgument = null;
143      Expression rightArgument = null;
144      {
145        var weights = leftArguments.Select(x => x.Item2);
146        leftArgument = sampleWithRepetition
147          ? leftArguments.SampleProportional(random, 1, weights, windowing: false).Select(x => x.Item1).First() :
148          leftArguments.SampleProportionalWithoutRepetition(random, 1, weights, windowing: false).Select(x => x.Item1).First();
149      }
150      {
151        var weights = rightArguments.Select(x => x.Item2);
152        rightArgument = sampleWithRepetition
153          ? rightArguments.SampleProportional(random, 1, weights).Select(x => x.Item1).First() :
154          rightArguments.SampleProportionalWithoutRepetition(random, 1, weights).Select(x => x.Item1).First();
155      }
156
157      var func = Expression.Function(name, transform, new Expression[] { leftArgument, rightArgument });
158      func.Label = Label;
159      return func;
160    }
161  }
162
163  public class ScalingTemplate : ExpressionTemplate {
164    private readonly IDistribution<double> scaledVariance;
165    // w * expr
166    public ScalingTemplate(IDistribution<double> scaledVariance = null) : base(ExpressionGenerator.Product) {
167      this.scaledVariance = scaledVariance;
168    }
169
170    public override Expression Instantiate(string name, IRandom random, bool sampleWithRepetition = false) {
171      var expr = SampleArguments(random, 1, sampleWithRepetition).First();
172
173      // use the evaluator to determine variance of the sampled expression and initialize the constant accordingly to reach the target variance
174      var @const = 1.0;
175      if (scaledVariance != null) {
176        var evaluator = new ExpressionEvaluator();
177        var data = evaluator.GenerateData(expr, 10000);
178        var variance = data[expr].VariancePop();
179        @const = scaledVariance.Sample() / variance;
180      }
181
182      var func = Expression.Function(name, transform, new Expression[] { Expression.Constant(name, @const), expr });
183      func.Label = "*";
184      return func;
185    }
186  }
187
188  public class OffsetTemplate : ExpressionTemplate {
189    private readonly IDistribution<double> offset;
190    // expr + offset
191    public OffsetTemplate(IDistribution<double> offset = null) : base(ExpressionGenerator.Sum) {
192      this.offset = offset;
193    }
194
195    public override Expression Instantiate(string name, IRandom random, bool sampleWithRepetition = false) {
196      var expr = SampleArguments(random, 1, sampleWithRepetition).First();
197
198      // use the evaluator to determine variance of the sampled expression and initialize the constant accordingly to reach the target offset
199      var @const = 0.0;
200      if (offset != null) {
201        var evaluator = new ExpressionEvaluator();
202        var data = evaluator.GenerateData(expr, 10000);
203        var average = data[expr].Average();
204        @const = offset.Sample() - average;
205      }
206
207      var func = Expression.Function(name, transform, new Expression[] { Expression.Constant(name, @const), expr });
208      func.Label = "+";
209      return func;
210    }
211  }
212
213  public class RangeTemplate : ExpressionTemplate {
214    private readonly IDistribution<double> minValue;
215    private readonly IDistribution<double> valueRange;
216    // expr + offset
217    public RangeTemplate(IDistribution<double> minValue = null, IDistribution<double> valueRange = null) : base(null) {
218      this.minValue = minValue;
219      this.valueRange = valueRange;
220    }
221
222    public override Expression Instantiate(string name, IRandom random, bool sampleWithRepetition = false) {
223      var expr = SampleArguments(random, 1, sampleWithRepetition).First();
224
225      // use the evaluator to determine variance of the sampled expression and initialize the constant accordingly to reach the target offset
226      var mult = 1.0;
227      var add = 0.0;
228
229      if (minValue != null || valueRange != null) {
230        var evaluator = new ExpressionEvaluator();
231        var data = evaluator.GenerateData(expr, 10000);
232        if (valueRange != null) {
233          var targetRange = valueRange.Sample();
234          var min = data[expr].Min();
235          var max = data[expr].Max();
236          var range = max - min;
237          mult = targetRange / range;
238          add = -min + min / mult;
239        }
240        if (minValue != null) {
241          var targetMin = minValue.Sample();
242          var min = data[expr].Min();
243          add += (targetMin - min) / mult;
244        }
245
246        expr = Expression.Function(name + "-toZero", ExpressionGenerator.Sum, new Expression[] { Expression.Constant("name-add0", add), expr });
247        expr.Label = "+";
248        expr = Expression.Function(name + "-mult", ExpressionGenerator.Product, new Expression[] { Expression.Constant("name-mult", mult), expr });
249        expr.Label = "*";
250      }
251
252      return expr;
253    }
254  }
255}
Note: See TracBrowser for help on using the repository browser.