Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
04/15/17 08:44:15 (7 years 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)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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;
Note: See TracChangeset for help on using the changeset viewer.