Legend:
- Unmodified
- Added
- Removed
-
stable
- Property svn:mergeinfo changed
-
stable/HeuristicLab.Problems.DataAnalysis.Symbolic
- Property svn:mergeinfo changed
-
stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/InfixExpressionParser.cs
r14565 r15131 33 33 /// Parses mathematical expressions in infix form. E.g. x1 * (3.0 * x2 + x3) 34 34 /// Identifier format (functions or variables): '_' | letter { '_' | letter | digit } 35 /// Variables names can be set under quotes "" or '' because variable names might contain spaces. 35 /// Variables names and variable values can be set under quotes "" or '' because variable names might contain spaces. 36 /// Variable = ident | " ident " | ' ident ' 36 37 /// It is also possible to use functions e.g. log("x1") or real-valued constants e.g. 3.1415 . 37 38 /// Variable names are case sensitive. Function names are not case sensitive. 39 /// 40 /// 41 /// S = Expr EOF 42 /// Expr = ['-' | '+'] Term { '+' Term | '-' Term } 43 /// Term = Fact { '*' Fact | '/' Fact } 44 /// Fact = '(' Expr ')' 45 /// | 'LAG' '(' varId ',' ['+' | '-' ] number ')' 46 /// | funcId '(' ArgList ')' 47 /// | VarExpr | number 48 /// ArgList = Expr { ',' Expr } 49 /// VarExpr = varId OptFactorPart 50 /// OptFactorPart = [ ('=' varVal | '[' ['+' | '-' ] number {',' ['+' | '-' ] number } ']' ) ] 51 /// varId = ident | ' ident ' | " ident " 52 /// varVal = ident | ' ident ' | " ident " 53 /// ident = '_' | letter { '_' | letter | digit } 38 54 /// </summary> 39 55 public sealed class InfixExpressionParser { 40 private enum TokenType { Operator, Identifier, Number, LeftPar, RightPar, Comma, End, NA };56 private enum TokenType { Operator, Identifier, Number, LeftPar, RightPar, LeftBracket, RightBracket, Comma, Eq, End, NA }; 41 57 private class Token { 42 58 internal double doubleVal; … … 65 81 private Constant constant = new Constant(); 66 82 private Variable variable = new Variable(); 83 private BinaryFactorVariable binaryFactorVar = new BinaryFactorVariable(); 84 private FactorVariable factorVar = new FactorVariable(); 67 85 68 86 private ProgramRootSymbol programRootSymbol = new ProgramRootSymbol(); … … 150 168 && str[pos] != '/' 151 169 && str[pos] != ')' 170 && str[pos] != ']' 152 171 && str[pos] != ',') { 153 172 sb.Append(str[pos]); … … 214 233 pos++; 215 234 yield return new Token { TokenType = TokenType.RightPar, strVal = ")" }; 235 } else if (str[pos] == '[') { 236 pos++; 237 yield return new Token { TokenType = TokenType.LeftBracket, strVal = "[" }; 238 } else if (str[pos] == ']') { 239 pos++; 240 yield return new Token { TokenType = TokenType.RightBracket, strVal = "]" }; 241 } else if (str[pos] == '=') { 242 pos++; 243 yield return new Token { TokenType = TokenType.Eq, strVal = "=" }; 216 244 } else if (str[pos] == ',') { 217 245 pos++; … … 222 250 } 223 251 } 224 225 // S = Expr EOF 226 // Expr = ['-' | '+'] Term { '+' Term | '-' Term } 227 // Term = Fact { '*' Fact | '/' Fact } 228 // Fact = '(' Expr ')' | funcId '(' ArgList ')' | varId | number 229 // ArgList = Expr { ',' Expr } 252 /// S = Expr EOF 230 253 private ISymbolicExpressionTreeNode ParseS(Queue<Token> tokens) { 231 254 var expr = ParseExpr(tokens); … … 237 260 return expr; 238 261 } 262 263 /// Expr = ['-' | '+'] Term { '+' Term | '-' Term } 239 264 private ISymbolicExpressionTreeNode ParseExpr(Queue<Token> tokens) { 240 265 var next = tokens.Peek(); … … 300 325 } 301 326 302 // Term= Fact { '*' Fact | '/' Fact }327 /// Term = Fact { '*' Fact | '/' Fact } 303 328 private ISymbolicExpressionTreeNode ParseTerm(Queue<Token> tokens) { 304 329 var factors = new List<ISymbolicExpressionTreeNode>(); … … 335 360 } 336 361 337 // Fact = '(' Expr ')' | 'LAG' '(' varId ',' ['+' | '-'] number ')' | funcId '(' ArgList ')' | varId | number 362 /// Fact = '(' Expr ')' 363 /// | 'LAG' '(' varId ',' ['+' | '-' ] number ')' 364 /// | funcId '(' ArgList ')' 365 /// | VarExpr | number 366 /// ArgList = Expr { ',' Expr } 367 /// VarExpr = varId OptFactorPart 368 /// OptFactorPart = [ ('=' varVal | '[' ['+' | '-' ] number {',' ['+' | '-' ] number } ']' ) ] 369 /// varId = ident | ' ident ' | " ident " 370 /// varVal = ident | ' ident ' | " ident " 371 /// ident = '_' | letter { '_' | letter | digit } 338 372 private ISymbolicExpressionTreeNode ParseFact(Queue<Token> tokens) { 339 373 var next = tokens.Peek(); … … 348 382 var idTok = tokens.Dequeue(); 349 383 if (tokens.Peek().TokenType == TokenType.LeftPar) { 350 // function identifier 384 // function identifier or LAG 351 385 var funcId = idTok.strVal.ToUpperInvariant(); 352 386 … … 394 428 } else { 395 429 // variable 396 var varNode = (VariableTreeNode)variable.CreateTreeNode(); 397 varNode.Weight = 1.0; 398 varNode.VariableName = idTok.strVal; 399 return varNode; 430 if (tokens.Peek().TokenType == TokenType.Eq) { 431 // binary factor 432 tokens.Dequeue(); // skip Eq 433 var valTok = tokens.Dequeue(); 434 if (valTok.TokenType != TokenType.Identifier) throw new ArgumentException("expected identifier"); 435 var binFactorNode = (BinaryFactorVariableTreeNode)binaryFactorVar.CreateTreeNode(); 436 binFactorNode.Weight = 1.0; 437 binFactorNode.VariableName = idTok.strVal; 438 binFactorNode.VariableValue = valTok.strVal; 439 return binFactorNode; 440 } else if (tokens.Peek().TokenType == TokenType.LeftBracket) { 441 // factor variable 442 var factorVariableNode = (FactorVariableTreeNode)factorVar.CreateTreeNode(); 443 factorVariableNode.VariableName = idTok.strVal; 444 445 tokens.Dequeue(); // skip [ 446 var weights = new List<double>(); 447 // at least one weight is necessary 448 var sign = 1.0; 449 if (tokens.Peek().TokenType == TokenType.Operator) { 450 var opToken = tokens.Dequeue(); 451 if (opToken.strVal == "+") sign = 1.0; 452 else if (opToken.strVal == "-") sign = -1.0; 453 else throw new ArgumentException(); 454 } 455 if (tokens.Peek().TokenType != TokenType.Number) throw new ArgumentException("number expected"); 456 var weightTok = tokens.Dequeue(); 457 weights.Add(sign * weightTok.doubleVal); 458 while (tokens.Peek().TokenType == TokenType.Comma) { 459 // skip comma 460 tokens.Dequeue(); 461 if (tokens.Peek().TokenType == TokenType.Operator) { 462 var opToken = tokens.Dequeue(); 463 if (opToken.strVal == "+") sign = 1.0; 464 else if (opToken.strVal == "-") sign = -1.0; 465 else throw new ArgumentException(); 466 } 467 weightTok = tokens.Dequeue(); 468 if (weightTok.TokenType != TokenType.Number) throw new ArgumentException("number expected"); 469 weights.Add(sign * weightTok.doubleVal); 470 } 471 var rightBracketToken = tokens.Dequeue(); 472 if (rightBracketToken.TokenType != TokenType.RightBracket) throw new ArgumentException("closing bracket ] expected"); 473 factorVariableNode.Weights = weights.ToArray(); 474 return factorVariableNode; 475 } else { 476 // variable 477 var varNode = (VariableTreeNode)variable.CreateTreeNode(); 478 varNode.Weight = 1.0; 479 varNode.VariableName = idTok.strVal; 480 return varNode; 481 } 400 482 } 401 483 } else if (next.TokenType == TokenType.Number) { -
stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/SymbolicExpressionImporter.cs
r14186 r15131 35 35 private const string INVOKESTART = "CALL"; 36 36 private const string TIMELAGSTART = "LAG"; 37 private Dictionary<string, Symbol> knownSymbols = new Dictionary<string, Symbol>() 37 private Dictionary<string, Symbol> knownSymbols = new Dictionary<string, Symbol>() 38 38 { 39 39 {"+", new Addition()}, … … 45 45 {"POW", new Power()}, 46 46 {"ROOT", new Root()}, 47 {"SQR", new Square()}, 48 {"SQRT", new SquareRoot()}, 47 49 {"SIN",new Sine()}, 48 50 {"COS", new Cosine()}, … … 74 76 {"PROG", new ProgramRootSymbol()}, 75 77 {"MAIN", new StartSymbol()}, 78 {"FACTOR", new FactorVariable() }, 79 {"BINFACTOR", new BinaryFactorVariable()} 76 80 }; 77 81 … … 82 86 TimeLag timeLag = new TimeLag(); 83 87 Integral integral = new Integral(); 88 FactorVariable factorVar = new FactorVariable(); 89 BinaryFactorVariable binFactorVar = new BinaryFactorVariable(); 84 90 85 91 ProgramRootSymbol programRootSymbol = new ProgramRootSymbol(); … … 136 142 tree.AddSubtree(ParseSexp(tokens)); 137 143 } 144 } else if (tokens.Peek().StringValue.StartsWith("FACTOR")) { 145 tree = ParseFactor(tokens); 146 } else if (tokens.Peek().StringValue.StartsWith("BINFACTOR")) { 147 tree = ParseBinaryFactor(tokens); 138 148 } else { 139 149 Token curToken = tokens.Dequeue(); … … 201 211 } 202 212 213 private ISymbolicExpressionTreeNode ParseFactor(Queue<Token> tokens) { 214 Token tok = tokens.Dequeue(); 215 Debug.Assert(tok.StringValue == "FACTOR"); 216 FactorVariableTreeNode t = (FactorVariableTreeNode)(new FactorVariable()).CreateTreeNode(); // create a new symbol each time on purpose 217 var varNameTok = tokens.Dequeue(); 218 Debug.Assert(tok.Symbol == TokenSymbol.SYMB); 219 t.VariableName = varNameTok.StringValue; 220 221 var weights = new List<double>(); 222 while (tokens.Peek().Symbol == TokenSymbol.NUMBER) { 223 weights.Add(tokens.Dequeue().DoubleValue); 224 } 225 226 t.Weights = weights.ToArray(); 227 228 // create a set of (virtual) values to match the number of weights 229 t.Symbol.VariableNames = new string[] { t.VariableName }; 230 t.Symbol.VariableValues = new[] 231 { new KeyValuePair<string, Dictionary<string,int>>( 232 t.VariableName, 233 weights.Select((_, i) => Tuple.Create(_,i)).ToDictionary(tup=>"X" + tup.Item2, tup=>tup.Item2)) }; 234 return t; 235 } 236 237 private ISymbolicExpressionTreeNode ParseBinaryFactor(Queue<Token> tokens) { 238 Token tok = tokens.Dequeue(); 239 Debug.Assert(tok.StringValue == "BINFACTOR"); 240 var t = (BinaryFactorVariableTreeNode)binFactorVar.CreateTreeNode(); 241 var varNameTok = tokens.Dequeue(); 242 Debug.Assert(varNameTok.Symbol == TokenSymbol.SYMB); 243 t.VariableName = varNameTok.StringValue; 244 245 var varValTok = tokens.Dequeue(); 246 Debug.Assert(varValTok.Symbol == TokenSymbol.SYMB); 247 t.VariableValue = varValTok.StringValue; 248 249 var weightTok = tokens.Dequeue(); 250 Debug.Assert(weightTok.Symbol == TokenSymbol.NUMBER); 251 t.Weight = weightTok.DoubleValue; 252 253 return t; 254 } 255 256 203 257 private ISymbolicExpressionTreeNode ParseLaggedVariable(Queue<Token> tokens) { 204 258 Token varTok = tokens.Dequeue();
Note: See TracChangeset
for help on using the changeset viewer.