using HeuristicLab.Common; using HeuristicLab.Core; using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; using HeuristicLab.Problems.DataAnalysis.Symbolic; namespace HeuristicLab.Problems.GeneticProgramming.GlucosePrediction { [StorableClass] [Item("Blood glucose level forecast grammar", "See MedGEC Workshop at GECCO 2016")] public class Grammar : SymbolicExpressionGrammar { [StorableConstructor] protected Grammar(bool deserializing) : base(deserializing) { } protected Grammar(Grammar original, Cloner cloner) : base(original, cloner) { } public Grammar() : base("Blood glucose level forecast grammar", "See MedGEC Workshop at GECCO 2016") { Initialize(); } public void Initialize() { var func = new SimpleSymbol("Func", "The root for the blood glucose forecasting model.", 3, 3); var exprGluc = new SimpleSymbol("ExprGluc", string.Empty, 1, 1); var exprIns = new SimpleSymbol("ExprIns", string.Empty, 1, 1); var exprCh = new SimpleSymbol("ExprCh", string.Empty, 1, 1); var predGlucData = new PredictedGlucoseVariableSymbol(); var realGlucData = new RealGlucoseVariableSymbol(); // operators for exprGluc var plusGluc = new SimpleSymbol("+", "+", 2, 2); var minusGluc = new SimpleSymbol("-", "-", 2, 2); var prodGluc = new SimpleSymbol("*", "*", 2, 2); var divGluc = new SimpleSymbol("/", "/", 2, 2); var expGluc = new SimpleSymbol("Exp", "Exp", 1, 1); var sinGluc = new SimpleSymbol("Sin", "Sin", 1, 1); var cosGluc = new SimpleSymbol("Cos", "Cos", 1, 1); var logGluc = new SimpleSymbol("Log", "Log", 1, 1); // var cteGluc = new CteSymbol(); // operators for exprCh var plusCh = new SimpleSymbol("+Ch", "+", 2, 2); var minusCh = new SimpleSymbol("-Ch", "-", 2, 2); var prodCh = new SimpleSymbol("*Ch", "*", 2, 2); var divCh = new SimpleSymbol("/Ch", "/", 2, 2); var expCh = new SimpleSymbol("ExpCh", "Exp", 1, 1); var sinCh = new SimpleSymbol("SinCh", "Sin", 1, 1); var cosCh = new SimpleSymbol("CosCh", "Cos", 1, 1); var logCh = new SimpleSymbol("LogCh", "Log", 1, 1); var curvedCh = new CurvedChVariableSymbol("CurvedCh", ""); // var cteCh = new CteSymbol(); // operators for exprIns var plusIns = new SimpleSymbol("+Ins", "+", 2, 2); var minusIns = new SimpleSymbol("-Ins", "-", 2, 2); var prodIns = new SimpleSymbol("*Ins", "*", 2, 2); var divIns = new SimpleSymbol("/Ins", "/", 2, 2); var expIns = new SimpleSymbol("ExpIns", "Exp", 1, 1); var sinIns = new SimpleSymbol("SinIns", "Sin", 1, 1); var cosIns = new SimpleSymbol("CosIns", "Cos", 1, 1); var logIns = new SimpleSymbol("LogIns", "Log", 1, 1); var curvedIns = new CurvedInsVariableSymbol("CurvedIns", ""); var realInsVar = new RealInsulineVariableSymbol(); var constSy = new Constant(); // var cteCh = new CteSymbol(); AddSymbol(func); AddSymbol(exprGluc); AddSymbol(exprIns); AddSymbol(exprCh); AddSymbol(predGlucData); AddSymbol(realGlucData); AddSymbol(plusGluc); AddSymbol(minusGluc); AddSymbol(prodGluc); AddSymbol(divGluc); AddSymbol(expGluc); AddSymbol(sinGluc); AddSymbol(cosGluc); AddSymbol(logGluc); AddSymbol(curvedCh); AddSymbol(plusCh); AddSymbol(minusCh); AddSymbol(prodCh); AddSymbol(divCh); AddSymbol(expCh); AddSymbol(sinCh); AddSymbol(cosCh); AddSymbol(logCh); AddSymbol(curvedIns); AddSymbol(plusIns); AddSymbol(minusIns); AddSymbol(prodIns); AddSymbol(divIns); AddSymbol(expIns); AddSymbol(sinIns); AddSymbol(cosIns); AddSymbol(logIns); AddSymbol(realInsVar); AddSymbol(constSy); // ::= + - AddAllowedChildSymbol(func, exprGluc, 0); AddAllowedChildSymbol(func, exprCh, 1); AddAllowedChildSymbol(func, exprIns, 2); /* # Glucose ::= ( ) | () |( ) |predictedData(k-) |realData(k-) */ var opGlucSet = new Symbol[] { plusGluc, minusGluc, prodGluc, divGluc, expGluc, sinGluc, cosGluc, logGluc, predGlucData, realGlucData, constSy }; foreach (var opGluc in opGlucSet) { AddAllowedChildSymbol(exprGluc, opGluc); } foreach (var parentOp in new Symbol[] { plusGluc, minusGluc, prodGluc, divGluc }) { foreach (var childOp in opGlucSet) { AddAllowedChildSymbol(parentOp, childOp, 0); AddAllowedChildSymbol(parentOp, childOp, 1); } } // ::= () foreach (var parentOp in new Symbol[] { expGluc, sinGluc, cosGluc, logGluc }) { foreach (var childOp in opGlucSet) { AddAllowedChildSymbol(parentOp, childOp, 0); } } /* # CH ::= ( ) | () |( ) |(getPrevData(1,k,1) * * ) # CH in 2 (0.041,24), 3 (0.027,36) and 4 (0.02,48) hours with 3 shapes of beta: ::= beta(0.041*Math.min(24,getPrevDataDistance(1,k,1)),2,5) |beta(0.041*Math.min(24,getPrevDataDistance(1,k,1)),3,3) |beta(0.041*Math.min(24,getPrevDataDistance(1,k,1)),5,2) |beta(0.027*Math.min(36,getPrevDataDistance(1,k,1)),2,5) |beta(0.027*Math.min(36,getPrevDataDistance(1,k,1)),3,3) |beta(0.027*Math.min(36,getPrevDataDistance(1,k,1)),5,2) |beta(0.02*Math.min(48,getPrevDataDistance(1,k,1)),2,5) |beta(0.02*Math.min(48,getPrevDataDistance(1,k,1)),3,3) |beta(0.02*Math.min(48,getPrevDataDistance(1,k,1)),5,2) */ var opChSet = new Symbol[] { plusCh, minusCh, prodCh, divCh, expCh, sinCh, cosCh, logCh, curvedCh, constSy }; foreach (var opCh in opChSet) { AddAllowedChildSymbol(exprCh, opCh); } foreach (var parentOp in new Symbol[] { plusCh, minusCh, prodCh, divCh }) { foreach (var childOp in opChSet) { AddAllowedChildSymbol(parentOp, childOp, 0); AddAllowedChildSymbol(parentOp, childOp, 1); } } // ::= () foreach (var parentOp in new Symbol[] { expCh, sinCh, cosCh, logCh }) { foreach (var childOp in opChSet) { AddAllowedChildSymbol(parentOp, childOp, 0); } } /* # Insulin: ## Sum of insulins in past 2h minus the peak ## Curve for the peak in past 2h ::= ( ) | () |( ) |getVariable(2,k-) |(getSumOfValues(24,k,2) - getMaxValue(24,k,2) (getMaxValue(24,k,2) )) # INS in 2 (0.041,24), 3 (0.027,36) and 4 (0.02,48) hours with 3 shapes of beta: ::= beta(0.041*Math.min(24,getMaxValueDistance(24,k,2)),2,5) |beta(0.041*Math.min(24,getMaxValueDistance(24,k,2)),3,3) |beta(0.041*Math.min(24,getMaxValueDistance(24,k,2)),5,2) |beta(0.027*Math.min(36,getMaxValueDistance(36,k,2)),2,5) |beta(0.027*Math.min(36,getMaxValueDistance(36,k,2)),3,3) |beta(0.027*Math.min(36,getMaxValueDistance(36,k,2)),5,2) |beta(0.02*Math.min(48,getMaxValueDistance(48,k,2)),2,5) |beta(0.02*Math.min(48,getMaxValueDistance(48,k,2)),3,3) |beta(0.02*Math.min(48,getMaxValueDistance(48,k,2)),5,2) */ var opInsSet = new Symbol[] { plusIns, minusIns, prodIns, divIns, expIns, sinIns, cosIns, logIns, realInsVar, curvedIns, constSy }; foreach (var opIns in opInsSet) { AddAllowedChildSymbol(exprIns, opIns); } // ::= ( ) // ::= ( ) foreach (var parentOp in new Symbol[] { plusIns, minusIns, prodIns, divIns }) { foreach (var childOp in opInsSet) { AddAllowedChildSymbol(parentOp, childOp, 0); AddAllowedChildSymbol(parentOp, childOp, 1); } } // ::= () foreach (var op in new Symbol[] { expIns, sinIns, cosIns, logIns }) { foreach (var childOp in opInsSet) { AddAllowedChildSymbol(op, childOp, 0); } } // root is func AddAllowedChildSymbol(StartSymbol, func); } public override IDeepCloneable Clone(Cloner cloner) { return new Grammar(this, cloner); } } }