Changeset 14873


Ignore:
Timestamp:
04/15/17 08:44:15 (6 weeks ago)
Author:
gkronber
Message:

#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)

Location:
branches/HeuristicLab.ExpressionGenerator/HeuristicLab.ExpressionGenerator/3.4
Files:
1 added
6 edited

Legend:

Unmodified
Added
Removed
  • branches/HeuristicLab.ExpressionGenerator/HeuristicLab.ExpressionGenerator/3.4/Expression.cs

    r14520 r14873  
    4242    }
    4343
    44     public IRandom Distribution { get; private set; }
    45 
    46     public Func<IEnumerable<double>, double> Transform { get; private set; }
    47 
    48     public double Value { get; private set; }
     44    public IRandom Distribution { get; private set; }  // only for random variables
     45
     46    public Func<IEnumerable<double>, double> Transform { get; private set; } // only for functions
     47
     48    public double Value { get; private set; } // only for constants
    4949
    5050    public Expression(string name, double value) {
     
    8585      switch (Type) {
    8686        case ExpressionType.Constant:
    87           sb.Append(Value.ToString("0.000", CultureInfo.CurrentCulture));
     87          sb.Append(Value.ToString("0.000", CultureInfo.InvariantCulture));
    8888          break;
    8989        case ExpressionType.RandomVariable:
     
    108108        case ExpressionType.Constant:
    109109          sb.Append(Value < 0
    110               ? string.Format("(- {0})", Math.Abs(Value).ToString("0.000", CultureInfo.CurrentCulture))
    111               : Value.ToString("0.000", CultureInfo.CurrentCulture));
     110              ? string.Format("(- {0})", Math.Abs(Value).ToString("0.000", CultureInfo.InvariantCulture))
     111              : Value.ToString("0.000", CultureInfo.InvariantCulture));
    112112          break;
    113113        case ExpressionType.RandomVariable:
  • branches/HeuristicLab.ExpressionGenerator/HeuristicLab.ExpressionGenerator/3.4/ExpressionEvaluator.cs

    r14409 r14873  
    5757
    5858    public Dictionary<Expression, List<double>> GenerateData(Expression expression, int rows) {
     59      return GenerateData(new [] {expression}, rows);
     60    }
     61    public Dictionary<Expression, List<double>> GenerateData(IEnumerable<Expression> expressions, int rows) {
    5962      var data = new Dictionary<Expression, List<double>>();
    6063      for (int i = 0; i < rows; ++i) {
    6164        evaluationCache.Clear();
    62         Evaluate(expression);
     65        foreach(var expr in expressions) Evaluate(expr);
    6366        foreach (var pair in evaluationCache) {
    6467          if (!data.ContainsKey(pair.Key))
  • branches/HeuristicLab.ExpressionGenerator/HeuristicLab.ExpressionGenerator/3.4/ExpressionGenerator.cs

    r14515 r14873  
    2323using System.Collections.Generic;
    2424using System.Linq;
     25using System.Runtime.InteropServices;
     26using HeuristicLab.Common;
    2527using HeuristicLab.Core;
    2628using HeuristicLab.Random;
     
    3032    public static IEnumerable<Expression> GenerateRandomDistributedVariables(int numberOfVariables, string variablePrefix, IRandom randomDistribution) {
    3133      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);
    3264    }
    3365
     
    70102    }
    71103
     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
    72138    #region static functions
    73     private static double Sum(IEnumerable<double> args) {
     139    public static double Sum(IEnumerable<double> args) {
    74140      return args.Sum();
    75141    }
    76142
    77     private static double Product(IEnumerable<double> args) {
     143    public static double Product(IEnumerable<double> args) {
    78144      return args.Aggregate((x, y) => x * y);
    79145    }
    80146
    81     private static double Division(IEnumerable<double> args) {
     147    public static double Division(IEnumerable<double> args) {
    82148      if (args.Count() == 1)
    83149        return 1 / args.First();
     
    86152    }
    87153
    88     private static double Subtraction(IEnumerable<double> args) {
     154    public static double Subtraction(IEnumerable<double> args) {
    89155      if (args.Count() == 1)
    90156        return -args.First();
     
    93159    }
    94160
    95     private static double Exp(IEnumerable<double> args) {
     161    public static double Exp(IEnumerable<double> args) {
    96162      return Math.Exp(args.Single());
    97163    }
    98164
    99     private static double Log(IEnumerable<double> args) {
     165    public static double Log(IEnumerable<double> args) {
    100166      return Math.Log(args.Single());
    101167    }
    102168
    103     private static double Square(IEnumerable<double> args) {
     169    public static double Square(IEnumerable<double> args) {
    104170      var v = args.Single();
    105171      return v * v;
  • branches/HeuristicLab.ExpressionGenerator/HeuristicLab.ExpressionGenerator/3.4/ExpressionTemplate.cs

    r14485 r14873  
    2323using System.Collections.Generic;
    2424using System.Linq;
     25using HeuristicLab.Common;
    2526using HeuristicLab.Core;
    2627using HeuristicLab.Random;
     
    2829namespace HeuristicLab.ExpressionGenerator {
    2930  public abstract class ExpressionTemplate {
    30     private List<Tuple<Expression, double>> arguments;
    31     private readonly Func<IEnumerable<double>, double> transform;
     31    protected List<Tuple<Expression, double>> arguments;
     32    protected readonly Func<IEnumerable<double>, double> transform;
    3233    public string Label { get; set; }
    3334
    3435    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) {
    3542      var weights = arguments.Select(x => x.Item2);
    3643      var args = sampleWithRepetition
    3744       ? arguments.SampleProportional(random, n, weights).Select(x => x.Item1)
    3845       : arguments.SampleProportionalWithoutRepetition(random, n, weights).Select(x => x.Item1);
    39       var func = Expression.Function(name, transform, args);
    40       func.Label = Label;
    41       return func;
     46      return args;
    4247    }
    4348
     
    5863    }
    5964
    60     public void AddArguments(IEnumerable<Expression> expressions, IEnumerable<double> weights) { 
     65    public void AddArguments(IEnumerable<Expression> expressions, IEnumerable<double> weights) {
    6166      arguments = arguments ?? new List<Tuple<Expression, double>>();
    6267      arguments.AddRange(expressions.Zip(weights, Tuple.Create));
     
    8792    }
    8893  }
     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  }
    89187}
  • branches/HeuristicLab.ExpressionGenerator/HeuristicLab.ExpressionGenerator/3.4/HeuristicLab.ExpressionGenerator.csproj

    r14505 r14873  
    7777    <Compile Include="ExpressionTemplate.cs" />
    7878    <Compile Include="Interfaces\IExpression.cs" />
     79    <Compile Include="PointDistribution.cs" />
    7980    <Compile Include="Plugin.cs" />
    8081  </ItemGroup>
  • branches/HeuristicLab.ExpressionGenerator/HeuristicLab.ExpressionGenerator/3.4/Properties

    • Property svn:ignore set to
      AssemblyInfo.cs
Note: See TracChangeset for help on using the changeset viewer.