Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Problems.GeneticProgramming.BloodGlucosePrediction/Interpreter.cs @ 14310

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

changed interpreter and grammar to smooth ch and ins uptake using a compartement model

File size: 8.0 KB
Line 
1using System;
2using System.Collections;
3using System.Collections.Generic;
4using System.Collections.ObjectModel;
5using System.Collections.Specialized;
6using System.Drawing.Design;
7using System.Linq;
8using HeuristicLab.Common;
9using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
10using HeuristicLab.Problems.DataAnalysis;
11using HeuristicLab.Problems.DataAnalysis.Symbolic;
12
13namespace HeuristicLab.Problems.GeneticProgramming.GlucosePrediction {
14  public static class Interpreter {
15    private class Data {
16      public double[] realGluc;
17      public double[] realIns;
18      public double[] realCh;
19      public Dictionary<ISymbolicExpressionTreeNode, double[]> precalculatedValues;
20    }
21
22    public static IEnumerable<double> Apply(ISymbolicExpressionTreeNode model, IDataset dataset, IEnumerable<int> rows) {
23      double[] targetGluc = dataset.GetDoubleValues("Glucose_target", rows).ToArray(); // only for skipping rows for which we should not produce an output
24
25      var data = new Data {
26        realGluc = dataset.GetDoubleValues("Glucose_Interpol", rows).ToArray(),
27        realIns = dataset.GetDoubleValues("Insuline", rows).ToArray(),
28        realCh = dataset.GetDoubleValues("CH", rows).ToArray(),
29        precalculatedValues = CreatePrecalculatedValues(model, dataset)
30      };
31      var predictions = new double[targetGluc.Length];
32      var rowsEnumerator = rows.GetEnumerator();
33      for (int k = 0; k < predictions.Length; k++, rowsEnumerator.MoveNext()) {
34        if (double.IsNaN(targetGluc[k])) {
35          predictions[k] = double.NaN;
36        } else {
37          var rawPred = InterpretRec(model, data, rowsEnumerator.Current);
38          predictions[k] = rawPred;
39        }
40      }
41      return predictions;
42    }
43
44    private static Dictionary<ISymbolicExpressionTreeNode, double[]> CreatePrecalculatedValues(ISymbolicExpressionTreeNode root, IDataset dataset) {
45      var dict = new Dictionary<ISymbolicExpressionTreeNode, double[]>();
46      // here we integrate ins or ch inputs over the whole day to generate smoothed ins/ch values with the same number of rows
47      // the integrated values are reset to zero whenever a new evluation period starts
48      foreach (var node in root.IterateNodesPrefix()) {
49        var curvedInsNode = node as CurvedInsVariableTreeNode;
50        var curvedChNode = node as CurvedChVariableTreeNode;
51        if (curvedInsNode != null) {
52          dict.Add(curvedInsNode, Integrate(curvedInsNode, dataset));
53        } else if (curvedChNode != null) {
54          dict.Add(curvedChNode, Integrate(curvedChNode, dataset));
55        }
56      }
57      return dict;
58    }
59
60    private static double[] Integrate(CurvedInsVariableTreeNode node, IDataset dataset) {
61      // d Q1 / dt = ins(t) - alpha * Q1(t)
62      // d Q2 / dt = alpha * (Q1(t) - Q2(t))
63      // S = Q1(t) + Q2(t)
64      var alpha = node.Alpha;
65
66      var ins = dataset.GetReadOnlyDoubleValues("Insuline");
67      var time = dataset.GetReadOnlyDoubleValues("HourMin").ToArray();
68
69      // TODO reset for new time intervals
70
71      double q1, q2, q1_prev, q2_prev;
72      // starting values: zeros
73      q1 = q2 = q1_prev = q2_prev = 0;
74      double[] s = new double[dataset.Rows];
75
76      for (int t = 1; t < dataset.Rows; t++) {
77        if (IsStartOfNewPeriod(time, t)) {
78          q1 = q2 = q1_prev = q2_prev = 0;
79        }
80        q1 = q1_prev + ins[t] - alpha * q1_prev;
81        q2 = q2_prev + alpha * (q1_prev - q2_prev);
82        s[t] = q1 + q2;
83        q1_prev = q1;
84        q2_prev = q2;
85
86      }
87      return s;
88    }
89
90    private static bool IsStartOfNewPeriod(double[] time, int t) {
91      return t == 0 ||
92             (time[t].IsAlmost(2005) && !time[t - 1].IsAlmost(2000));
93    }
94
95
96    private static double[] Integrate(CurvedChVariableTreeNode node, IDataset dataset) {
97      // d Q1 / dt = ins(t) - alpha * Q1(t)
98      // d Q2 / dt = alpha * (Q1(t) - Q2(t))
99      // S = Q1(t) + Q2(t)
100      var alpha = node.Alpha;
101
102      var ch = dataset.GetReadOnlyDoubleValues("CH");
103      var time = dataset.GetReadOnlyDoubleValues("HourMin").ToArray();
104
105      // TODO reset for new time intervals
106
107      double q1, q2, q1_prev, q2_prev;
108      // starting values: zeros
109      q1 = q2 = q1_prev = q2_prev = 0;
110      double[] s = new double[dataset.Rows];
111
112      for (int t = 1; t < dataset.Rows; t++) {
113        if (IsStartOfNewPeriod(time, t)) {
114          q1 = q2 = q1_prev = q2_prev = 0;
115        }
116        q1 = q1_prev + ch[t] - alpha * q1_prev;
117        q2 = q2_prev + alpha * (q1_prev - q2_prev);
118        s[t] = q1 + q2;
119        q1_prev = q1;
120        q2_prev = q2;
121
122      }
123      return s;
124    }
125
126    private static double InterpretRec(ISymbolicExpressionTreeNode node, Data data, int k) {
127      if (node.Symbol is SimpleSymbol) {
128        switch (node.Symbol.Name) {
129          case "+":
130          case "+Ins":
131          case "+Ch": {
132              return InterpretRec(node.GetSubtree(0), data, k) + InterpretRec(node.GetSubtree(1), data, k);
133            }
134          case "-":
135          case "-Ins":
136          case "-Ch": {
137              return InterpretRec(node.GetSubtree(0), data, k) - InterpretRec(node.GetSubtree(1), data, k);
138            }
139          case "*":
140          case "*Ins":
141          case "*Ch": {
142              return InterpretRec(node.GetSubtree(0), data, k) * InterpretRec(node.GetSubtree(1), data, k);
143            }
144          case "/Ch":
145          case "/Ins":
146          case "/": {
147              return InterpretRec(node.GetSubtree(0), data, k) / InterpretRec(node.GetSubtree(1), data, k);
148            }
149          case "Exp":
150          case "ExpIns":
151          case "ExpCh": {
152              return Math.Exp(InterpretRec(node.GetSubtree(0), data, k));
153            }
154          case "Sin":
155          case "SinIns":
156          case "SinCh": {
157              return Math.Sin(InterpretRec(node.GetSubtree(0), data, k));
158            }
159          case "CosCh":
160          case "CosIns":
161          case "Cos": {
162              return Math.Cos(InterpretRec(node.GetSubtree(0), data, k));
163            }
164          case "LogCh":
165          case "LogIns":
166          case "Log": {
167              return Math.Log(InterpretRec(node.GetSubtree(0), data, k));
168            }
169          case "Func": {
170              // <exprgluc> + <exprch> - <exprins>
171              return InterpretRec(node.GetSubtree(0), data, k)
172                     + InterpretRec(node.GetSubtree(1), data, k)
173                     - InterpretRec(node.GetSubtree(2), data, k);
174            }
175          case "ExprGluc": {
176              return InterpretRec(node.GetSubtree(0), data, k);
177            }
178          case "ExprCh": {
179              return InterpretRec(node.GetSubtree(0), data, k);
180            }
181          case "ExprIns": {
182              return InterpretRec(node.GetSubtree(0), data, k);
183            }
184          default: {
185              throw new InvalidProgramException("Found an unknown symbol " + node.Symbol);
186            }
187        }
188      } else if (node.Symbol is PredictedGlucoseVariableSymbol) {
189        throw new NotSupportedException();
190      } else if (node.Symbol is RealGlucoseVariableSymbol) {
191        var n = (RealGlucoseVariableTreeNode)node;
192        if (k + n.RowOffset < 0 || k + n.RowOffset >= data.realGluc.Length) return double.NaN;
193        return data.realGluc[k + n.RowOffset];
194      } else if (node.Symbol is CurvedChVariableSymbol) {
195        return data.precalculatedValues[node][k];
196      } else if (node.Symbol is RealInsulineVariableSymbol) {
197        throw new NotSupportedException();
198      } else if (node.Symbol is CurvedInsVariableSymbol) {
199        return data.precalculatedValues[node][k];
200      } else if (node.Symbol is Constant) {
201        var n = (ConstantTreeNode)node;
202        return n.Value;
203      } else {
204        throw new InvalidProgramException("found unknown symbol " + node.Symbol);
205      }
206    }
207
208    private static double Beta(double x, double alpha, double beta) {
209      return 1.0 / alglib.beta(alpha, beta) * Math.Pow(x, alpha - 1) * Math.Pow(1 - x, beta - 1);
210    }
211  }
212}
Note: See TracBrowser for help on using the repository browser.