[16303] | 1 | using System;
|
---|
| 2 | using System.Collections.Generic;
|
---|
| 3 | using System.Linq;
|
---|
| 4 | using HeuristicLab.Common;
|
---|
| 5 | using HeuristicLab.Core;
|
---|
| 6 | using HeuristicLab.Data;
|
---|
| 7 | using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
|
---|
| 8 | using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
|
---|
| 9 | using HeuristicLab.Problems.DataAnalysis;
|
---|
| 10 | using HeuristicLab.Problems.DataAnalysis.Symbolic;
|
---|
| 11 |
|
---|
[16328] | 12 | namespace HeuristicLab.Algorithms.DataAnalysis.Symbolic {
|
---|
[16303] | 13 | [StorableClass]
|
---|
| 14 | [Item("SymbolicDataAnalysisIntervalArithmeticInterpreter", "Interpreter for interval arithmetic within symbolic regression.")]
|
---|
[16328] | 15 | public sealed class IntervalInterpreter : ParameterizedNamedItem, IStatefulItem {
|
---|
| 16 |
|
---|
[16303] | 17 | private const string EvaluatedSolutionsParameterName = "EvaluatedSolutions";
|
---|
| 18 | public IFixedValueParameter<IntValue> EvaluatedSolutionsParameter {
|
---|
| 19 | get { return (IFixedValueParameter<IntValue>)Parameters[EvaluatedSolutionsParameterName]; }
|
---|
| 20 | }
|
---|
| 21 |
|
---|
| 22 | public int EvaluatedSolutions {
|
---|
| 23 | get { return EvaluatedSolutionsParameter.Value.Value; }
|
---|
| 24 | set { EvaluatedSolutionsParameter.Value.Value = value; }
|
---|
| 25 | }
|
---|
| 26 |
|
---|
[16328] | 27 | private IntervalInterpreter(bool deserializing) : base(deserializing) { }
|
---|
| 28 | private IntervalInterpreter(IntervalInterpreter original, Cloner cloner)
|
---|
[16303] | 29 | : base(original, cloner) { }
|
---|
| 30 |
|
---|
[16323] | 31 | public IntervalInterpreter()
|
---|
[16303] | 32 | : base("SymbolicDataAnalysisIntervalArithmeticInterpreter", "Interpreter for interval arithmetic within symbolic regression.") { }
|
---|
| 33 |
|
---|
| 34 | public override IDeepCloneable Clone(Cloner cloner) {
|
---|
[16323] | 35 | return new IntervalInterpreter(this, cloner);
|
---|
[16303] | 36 | }
|
---|
| 37 |
|
---|
[16328] | 38 | #region IStatefulItem Members
|
---|
| 39 | public void InitializeState() {
|
---|
| 40 | EvaluatedSolutions = 0;
|
---|
| 41 | }
|
---|
| 42 | public void ClearState() { }
|
---|
| 43 | #endregion
|
---|
| 44 |
|
---|
| 45 |
|
---|
| 46 | public Interval GetSymbolicExressionTreeIntervals(ISymbolicExpressionTree tree, IEnumerable<int> rows, out Dictionary<ISymbolicExpressionTreeNode, Interval> intervals) {
|
---|
| 47 | intervals = new Dictionary<ISymbolicExpressionTreeNode, Interval>();
|
---|
| 48 | var state = PrepareInterpreterState(tree, rows);
|
---|
| 49 | var x = Evaluate(state, intervals);
|
---|
| 50 |
|
---|
| 51 | return x;
|
---|
| 52 | }
|
---|
| 53 |
|
---|
| 54 | public Interval GetSymbolicExressionTreeIntervals(ISymbolicExpressionTree tree, IDataset dataset, IEnumerable<int> rows,
|
---|
| 55 | Dictionary<string, Interval> customIntervals, out Dictionary<ISymbolicExpressionTreeNode, Interval> intervals) {
|
---|
| 56 | intervals = new Dictionary<ISymbolicExpressionTreeNode, Interval>();
|
---|
| 57 | var state = PrepareInterpreterState(tree, rows, dataset, customIntervals);
|
---|
| 58 | var x = Evaluate(state, intervals);
|
---|
| 59 |
|
---|
| 60 | return x;
|
---|
| 61 | }
|
---|
| 62 |
|
---|
| 63 | public Interval GetSymbolicExressionTreeIntervals(ISymbolicExpressionTree tree, IDataset dataset, IEnumerable<int> rows,
|
---|
| 64 | out Dictionary<ISymbolicExpressionTreeNode, Interval> intervals) {
|
---|
| 65 | intervals = new Dictionary<ISymbolicExpressionTreeNode, Interval>();
|
---|
| 66 | var state = PrepareInterpreterState(tree, rows, dataset);
|
---|
| 67 | var x = Evaluate(state, intervals);
|
---|
| 68 |
|
---|
| 69 | return x;
|
---|
| 70 | }
|
---|
| 71 |
|
---|
[16303] | 72 | private readonly object syncRoot = new object();
|
---|
| 73 |
|
---|
[16328] | 74 | private static InterpreterState PrepareInterpreterState(ISymbolicExpressionTree tree,
|
---|
[16313] | 75 | IEnumerable<int> rows, IDataset dataset = null, Dictionary<string, Interval> customIntervals = null) {
|
---|
[16303] | 76 | Instruction[] code = SymbolicExpressionTreeCompiler.Compile(tree, OpCodes.MapSymbolToOpCode);
|
---|
| 77 | int necessaryArgStackSize = 0;
|
---|
[16328] | 78 |
|
---|
| 79 | foreach (Instruction instr in code) {
|
---|
[16303] | 80 | if (instr.opCode == OpCodes.Variable) {
|
---|
| 81 | var variableTreeNode = (VariableTreeNode)instr.dynamicNode;
|
---|
| 82 | IList<double> values = new List<double>();
|
---|
| 83 |
|
---|
[16313] | 84 | if (dataset != null && customIntervals != null) {
|
---|
| 85 | if (customIntervals.ContainsKey(variableTreeNode.VariableName)) {
|
---|
| 86 | instr.data = customIntervals[variableTreeNode.VariableName];
|
---|
[16328] | 87 | }
|
---|
| 88 | else {
|
---|
[16313] | 89 | foreach (var rowEnum in rows) {
|
---|
| 90 | values.Add(dataset.GetReadOnlyDoubleValues(variableTreeNode.VariableName)[rowEnum]);
|
---|
| 91 | }
|
---|
| 92 | instr.data = new Interval(values.Min(), values.Max());
|
---|
| 93 | }
|
---|
[16328] | 94 | }
|
---|
| 95 | else if (dataset != null) {
|
---|
| 96 | foreach (var rowEnum in rows) {
|
---|
[16303] | 97 | values.Add(dataset.GetReadOnlyDoubleValues(variableTreeNode.VariableName)[rowEnum]);
|
---|
| 98 | }
|
---|
| 99 | instr.data = new Interval(values.Min(), values.Max());
|
---|
[16328] | 100 | }
|
---|
| 101 | else if (customIntervals != null) {
|
---|
| 102 | if (customIntervals.ContainsKey(variableTreeNode.VariableName)) {
|
---|
[16313] | 103 | instr.data = customIntervals[variableTreeNode.VariableName];
|
---|
| 104 | }
|
---|
[16328] | 105 | }
|
---|
| 106 | else {
|
---|
[16313] | 107 | throw new Exception("No valid input for variables!");
|
---|
[16303] | 108 | }
|
---|
| 109 | }
|
---|
| 110 | }
|
---|
| 111 |
|
---|
| 112 | return new InterpreterState(code, necessaryArgStackSize);
|
---|
| 113 | }
|
---|
| 114 |
|
---|
| 115 | private Interval Evaluate(InterpreterState state, Dictionary<ISymbolicExpressionTreeNode, Interval> intervals) {
|
---|
| 116 | Instruction currentInstr = state.NextInstruction();
|
---|
| 117 | switch (currentInstr.opCode) {
|
---|
| 118 | //Elementary arithmetic rules
|
---|
| 119 | case OpCodes.Add: {
|
---|
| 120 | var s = Evaluate(state, intervals);
|
---|
| 121 | for (int i = 1; i < currentInstr.nArguments; i++) {
|
---|
| 122 | s = Interval.Add(s, Evaluate(state, intervals));
|
---|
| 123 | }
|
---|
| 124 | intervals.Add(currentInstr.dynamicNode, s);
|
---|
| 125 | return s;
|
---|
| 126 | }
|
---|
| 127 | case OpCodes.Sub: {
|
---|
| 128 | var s = Evaluate(state, intervals);
|
---|
| 129 | for (int i = 1; i < currentInstr.nArguments; i++) {
|
---|
| 130 | s = Interval.Subtract(s, Evaluate(state, intervals));
|
---|
| 131 | }
|
---|
| 132 | intervals.Add(currentInstr.dynamicNode, s);
|
---|
| 133 | return s;
|
---|
| 134 | }
|
---|
| 135 | case OpCodes.Mul: {
|
---|
| 136 | var s = Evaluate(state, intervals);
|
---|
| 137 | for (int i = 1; i < currentInstr.nArguments; i++) {
|
---|
| 138 | s = Interval.Multiply(s, Evaluate(state, intervals));
|
---|
| 139 | }
|
---|
| 140 | intervals.Add(currentInstr.dynamicNode, s);
|
---|
| 141 | return s;
|
---|
| 142 | }
|
---|
| 143 | case OpCodes.Div: {
|
---|
| 144 | var s = Evaluate(state, intervals);
|
---|
| 145 | for (int i = 1; i < currentInstr.nArguments; i++) {
|
---|
| 146 | s = Interval.Divide(s, Evaluate(state, intervals));
|
---|
| 147 | }
|
---|
| 148 | intervals.Add(currentInstr.dynamicNode, s);
|
---|
| 149 | return s;
|
---|
| 150 | }
|
---|
| 151 | //Trigonometric functions
|
---|
| 152 | case OpCodes.Sin: {
|
---|
| 153 | var s = Interval.Sine(Evaluate(state, intervals));
|
---|
| 154 | intervals.Add(currentInstr.dynamicNode, s);
|
---|
| 155 | return s;
|
---|
| 156 | }
|
---|
| 157 | case OpCodes.Cos: {
|
---|
| 158 | var s = Interval.Cosine(Evaluate(state, intervals));
|
---|
| 159 | intervals.Add(currentInstr.dynamicNode, s);
|
---|
| 160 | return s;
|
---|
| 161 | }
|
---|
| 162 | case OpCodes.Tan: {
|
---|
| 163 | var s = Interval.Tangens(Evaluate(state, intervals));
|
---|
| 164 | intervals.Add(currentInstr.dynamicNode, s);
|
---|
| 165 | return s;
|
---|
| 166 | }
|
---|
| 167 | //Exponential functions
|
---|
| 168 | case OpCodes.Log: {
|
---|
| 169 | var s = Interval.Logarithm(Evaluate(state, intervals));
|
---|
| 170 | intervals.Add(currentInstr.dynamicNode, s);
|
---|
| 171 | return s;
|
---|
| 172 | }
|
---|
| 173 | case OpCodes.Exp: {
|
---|
| 174 | var s = Interval.Exponential(Evaluate(state, intervals));
|
---|
| 175 | intervals.Add(currentInstr.dynamicNode, s);
|
---|
| 176 | return s;
|
---|
| 177 | }
|
---|
| 178 | case OpCodes.Power: {
|
---|
| 179 | var s = Evaluate(state, intervals);
|
---|
| 180 | for (int i = 1; i < currentInstr.nArguments; i++) {
|
---|
| 181 | s = Interval.Power(s, Evaluate(state, intervals));
|
---|
| 182 | }
|
---|
| 183 | intervals.Add(currentInstr.dynamicNode, s);
|
---|
| 184 | return s;
|
---|
| 185 | }
|
---|
[16323] | 186 | case OpCodes.Square: {
|
---|
| 187 | var s = Interval.Square(Evaluate(state, intervals));
|
---|
| 188 | intervals.Add(currentInstr.dynamicNode, s);
|
---|
| 189 | return s;
|
---|
| 190 | }
|
---|
[16303] | 191 | case OpCodes.Root: {
|
---|
| 192 | var s = Evaluate(state, intervals);
|
---|
| 193 | for (int i = 1; i < currentInstr.nArguments; i++) {
|
---|
| 194 | s = Interval.Root(s, Evaluate(state, intervals));
|
---|
| 195 | }
|
---|
| 196 | intervals.Add(currentInstr.dynamicNode, s);
|
---|
| 197 | return s;
|
---|
| 198 | }
|
---|
[16323] | 199 | case OpCodes.SquareRoot: {
|
---|
| 200 | var s = Interval.SquareRoot(Evaluate(state, intervals));
|
---|
| 201 | intervals.Add(currentInstr.dynamicNode, s);
|
---|
| 202 | return s;
|
---|
| 203 | }
|
---|
[16303] | 204 | //Variables, Constants, ...
|
---|
| 205 | case OpCodes.Variable: {
|
---|
| 206 | intervals.Add(currentInstr.dynamicNode, (Interval)currentInstr.data);
|
---|
| 207 | return (Interval)currentInstr.data;
|
---|
| 208 | }
|
---|
| 209 | case OpCodes.Constant: {
|
---|
| 210 | var constTreeNode = (ConstantTreeNode)currentInstr.dynamicNode;
|
---|
| 211 | var inter = new Interval(constTreeNode.Value, constTreeNode.Value);
|
---|
| 212 | intervals.Add(currentInstr.dynamicNode, inter);
|
---|
| 213 | return inter;
|
---|
| 214 | }
|
---|
| 215 | default:
|
---|
| 216 | throw new NotSupportedException();
|
---|
| 217 | }
|
---|
| 218 | }
|
---|
| 219 | }
|
---|
| 220 | }
|
---|