Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2704_HeuristicLab.ExpressionGenerator/HeuristicLab.ExpressionGenerator/3.4/Expression.cs @ 17800

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

#2704: added more expression templates

File size: 7.2 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; // only for functions
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("E4", 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("E4", CultureInfo.InvariantCulture))
111              : Value.ToString("E4", 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.