Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.ExpressionGenerator/HeuristicLab.ExpressionGenerator/3.4/Expression.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.1 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.Globalization;
25using System.Linq;
26using System.Text;
27using HeuristicLab.Core;
28using HeuristicLab.Random;
29
30namespace HeuristicLab.ExpressionGenerator {
31  public class Expression : IExpression {
32    // unique name for each expression
33    public string Name { get; set; }
34    // optional label (non-unique) - useful for string (infix) representations
35    public string Label { get; set; }
36
37    public ExpressionType Type { get; private set; }
38
39    private readonly List<Expression> arguments;
40    public IEnumerable<Expression> Arguments {
41      get { return arguments ?? Enumerable.Empty<Expression>(); }
42    }
43
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
49
50    public Expression(string name, double value) {
51      Type = ExpressionType.Constant;
52      Value = value;
53      Name = name;
54    }
55
56    public Expression(string name, IRandom distribution) {
57      Type = ExpressionType.RandomVariable;
58      Distribution = distribution;
59      Name = name;
60    }
61
62    public Expression(string name, Func<IEnumerable<double>, double> transform, IEnumerable<Expression> arguments) {
63      Type = ExpressionType.Function;
64      Transform = transform;
65      this.arguments = this.arguments ?? new List<Expression>();
66      this.arguments.AddRange(arguments);
67      Name = name;
68    }
69
70    public static Expression Constant(string name, double value) {
71      return new Expression(name, value);
72    }
73
74    public static Expression RandomVariable(string name, IRandom distribution) {
75      return new Expression(name, distribution);
76    }
77
78    public static Expression Function(string name, Func<IEnumerable<double>, double> transform, IEnumerable<Expression> arguments) {
79      return new Expression(name, transform, arguments);
80    }
81
82    public override string ToString() {
83      var sb = new StringBuilder();
84
85      switch (Type) {
86        case ExpressionType.Constant:
87          sb.Append(Value.ToString("0.000", CultureInfo.InvariantCulture));
88          break;
89        case ExpressionType.RandomVariable:
90          sb.Append(string.Format("{0} ~ {1}", Name, GetStringDescription(Distribution)));
91          break;
92        case ExpressionType.Function:
93          sb.Append(string.Format("{0} = f(", Name));
94          if (Arguments.Any()) {
95            for (int i = 0; i < arguments.Count - 1; ++i)
96              sb.Append(string.Format("{0}, ", arguments[i].Name));
97            sb.Append(string.Format("{0})", arguments.Last().Name));
98          }
99          break;
100      }
101
102      return sb.ToString();
103    }
104
105    public string PrintInfix() {
106      var sb = new StringBuilder();
107      switch (Type) {
108        case ExpressionType.Constant:
109          sb.Append(Value < 0
110              ? string.Format("(- {0})", Math.Abs(Value).ToString("0.000", CultureInfo.InvariantCulture))
111              : Value.ToString("0.000", CultureInfo.InvariantCulture));
112          break;
113        case ExpressionType.RandomVariable:
114          sb.Append(Name);
115          break;
116        case ExpressionType.Function:
117          if (!Arguments.Any())
118            break;
119          var args = Arguments.ToList();
120          // the Label should be known to the infix parser
121          if (Label == "+" || Label == "-" || Label == "*" || Label == "/") {
122            if (args.Count == 1) {
123              sb.Append(string.Format(Label == "/" ? "1 / {0}" : "{0}", args[0].PrintInfix()));
124            } else {
125              if (Label == "/") {
126                sb.Append(string.Format("{0} / ", args[0].PrintInfix()));
127                var remaining = args.Count - 1;
128                if (remaining == 1)
129                  sb.Append(args[1].PrintInfix());
130                else {
131                  sb.Append("(");
132                  var last = args.Last();
133                  for (int i = 1; i < args.Count - 1; ++i) {
134                    var arg = args[i];
135                    sb.Append(string.Format("{0} {1} ", arg.PrintInfix(), "*"));
136                  }
137                  sb.Append(string.Format("{0})", last.PrintInfix()));
138                }
139              } else {
140                sb.Append("(");
141                var last = args.Last();
142                for (int i = 0; i < args.Count - 1; ++i) {
143                  var arg = args[i];
144                  sb.Append(string.Format("{0} {1} ", arg.PrintInfix(), Label));
145                }
146                sb.Append(string.Format("{0})", last.PrintInfix()));
147              }
148            }
149          } else {
150            sb.Append(string.Format("{0}(", Label));
151            var last = args.Last();
152            for (int i = 0; i < args.Count - 1; ++i) {
153              var arg = args[i];
154              sb.Append(string.Format("{0}, ", arg.PrintInfix()));
155            }
156            sb.Append(string.Format("{0})", last.PrintInfix()));
157          }
158          break;
159      }
160      return sb.ToString();
161    }
162
163    public string PrintDot() {
164      var stack = new Stack<Expression>();
165      stack.Push(this);
166
167      var sb = new StringBuilder();
168      sb.AppendLine("digraph g {");
169
170      while (stack.Count > 0) {
171        var top = stack.Pop();
172
173        if (!top.Arguments.Any())
174          continue;
175
176        foreach (var arg in top.Arguments) {
177          var from = top.Arguments.Any() ? top.Name : top.ToString();
178          var to = arg.Arguments.Any() ? arg.Name : arg.ToString();
179          sb.AppendLine(string.Format("\"{0}\" -> \"{1}\";", from, to));
180          stack.Push(arg);
181        }
182      }
183
184      sb.AppendLine("}");
185      return sb.ToString();
186    }
187
188    private static string GetStringDescription(IRandom random) {
189      var normal = random as NormalDistributedRandom;
190      if (normal != null)
191        return string.Format("N({0}, {1})", normal.Mu, normal.Sigma);
192
193      var uniform = random as UniformDistributedRandom;
194      if (uniform != null)
195        return string.Format("U({0}, {1})", uniform.Min, uniform.Max);
196
197      var gamma = random as GammaDistributedRandom;
198      if (gamma != null)
199        return string.Format("G({0}, {1})", gamma.Shape, gamma.Rate);
200
201      return random.ToString();
202    }
203  }
204}
Note: See TracBrowser for help on using the repository browser.