Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
10/23/16 09:44:29 (7 years ago)
Author:
gkronber
Message:

#2650: merged r14332:14350 from trunk to branch

Location:
branches/symbreg-factors-2650
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • branches/symbreg-factors-2650

  • branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic

  • branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/InfixExpressionParser.cs

    r14330 r14351  
    2626using System.Text;
    2727using HeuristicLab.Collections;
     28using HeuristicLab.Common;
    2829using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
    2930
     
    4849  /// </summary>
    4950  public sealed class InfixExpressionParser {
    50     private enum TokenType { Operator, Identifier, Number, LeftPar, RightPar, Eq, End, NA };
     51    private enum TokenType { Operator, Identifier, Number, LeftPar, RightPar, Comma, Eq, End, NA };
    5152    private class Token {
    5253      internal double doubleVal;
     
    114115        { "MEAN", new Average()},
    115116        { "IF", new IfThenElse()},
    116         { ">", new GreaterThan()},
    117         { "<", new LessThan()},
     117        { "GT", new GreaterThan()},
     118        { "LT", new LessThan()},
    118119        { "AND", new And()},
    119120        { "OR", new Or()},
     
    121122        { "XOR", new Xor()},
    122123        { "DIFF", new Derivative()},
     124        { "LAG", new LaggedVariable() },
    123125      };
    124126
     
    150152        }
    151153        if (char.IsDigit(str[pos])) {
    152           // read number (=> read until white space or operator)
     154          // read number (=> read until white space or operator or comma)
    153155          var sb = new StringBuilder();
    154156          sb.Append(str[pos]);
     
    159161            && str[pos] != '*'
    160162            && str[pos] != '/'
    161             && str[pos] != ')') {
     163            && str[pos] != ')'
     164            && str[pos] != ',') {
    162165            sb.Append(str[pos]);
    163166            pos++;
     
    226229          pos++;
    227230          yield return new Token { TokenType = TokenType.Eq, strVal = "=" };
     231        } else if (str[pos] == ',') {
     232          pos++;
     233          yield return new Token { TokenType = TokenType.Comma, strVal = "," };
    228234        } else {
    229235          throw new ArgumentException("Invalid character: " + str[pos]);
     
    232238    }
    233239
     240    // S       = Expr EOF
     241    // Expr    = ['-' | '+'] Term { '+' Term | '-' Term }
     242    // Term    = Fact { '*' Fact | '/' Fact }
     243    // Fact    = '(' Expr ')' | funcId '(' ArgList ')' | varId | number
     244    // ArgList = Expr { ',' Expr }
    234245    private ISymbolicExpressionTreeNode ParseS(Queue<Token> tokens) {
    235246      var expr = ParseExpr(tokens);
     
    339350    }
    340351
    341     // Fact = '(' Expr ')' | funcId '(' Expr ')' | varId [ = valId ] | number
     352    // Fact = '(' Expr ')' | 'LAG' '(' varId ',' ['+' | '-' ] number ')' | funcId '(' Expr ')' | varId [ = valId ] | number
    342353    private ISymbolicExpressionTreeNode ParseFact(Queue<Token> tokens) {
    343354      var next = tokens.Peek();
     
    359370          if (lPar.TokenType != TokenType.LeftPar)
    360371            throw new ArgumentException("expected (");
    361           var expr = ParseExpr(tokens);
     372
     373          // handle 'lag' specifically
     374          if (funcNode.Symbol is LaggedVariable) {
     375            var varId = tokens.Dequeue();
     376            if (varId.TokenType != TokenType.Identifier) throw new ArgumentException("Identifier expected. Format for lagged variables: \"lag(x, -1)\"");
     377            var comma = tokens.Dequeue();
     378            if (comma.TokenType != TokenType.Comma) throw new ArgumentException("',' expected, Format for lagged variables: \"lag(x, -1)\"");
     379            double sign = 1.0;
     380            if (tokens.Peek().strVal == "+" || tokens.Peek().strVal == "-") {
     381              // read sign
     382              var signTok = tokens.Dequeue();
     383              if (signTok.strVal == "-") sign = -1.0;
     384            }
     385            var lagToken = tokens.Dequeue();
     386            if (lagToken.TokenType != TokenType.Number) throw new ArgumentException("Number expected, Format for lagged variables: \"lag(x, -1)\"");
     387            if (!lagToken.doubleVal.IsAlmost(Math.Round(lagToken.doubleVal)))
     388              throw new ArgumentException("Time lags must be integer values");
     389            var laggedVarNode = funcNode as LaggedVariableTreeNode;
     390            laggedVarNode.VariableName = varId.strVal;
     391            laggedVarNode.Lag = (int)Math.Round(sign * lagToken.doubleVal);
     392            laggedVarNode.Weight = 1.0;
     393          } else {
     394            // functions
     395            var args = ParseArgList(tokens);
     396            // check number of arguments
     397            if (funcNode.Symbol.MinimumArity > args.Length || funcNode.Symbol.MaximumArity < args.Length) {
     398              throw new ArgumentException(string.Format("Symbol {0} requires between {1} and  {2} arguments.", funcId,
     399                funcNode.Symbol.MinimumArity, funcNode.Symbol.MaximumArity));
     400            }
     401            foreach (var arg in args) funcNode.AddSubtree(arg);
     402          }
     403
    362404          var rPar = tokens.Dequeue();
    363405          if (rPar.TokenType != TokenType.RightPar)
    364406            throw new ArgumentException("expected )");
    365407
    366           funcNode.AddSubtree(expr);
    367408          return funcNode;
    368409        } else {
     
    396437    }
    397438
     439    // ArgList = Expr { ',' Expr }
     440    private ISymbolicExpressionTreeNode[] ParseArgList(Queue<Token> tokens) {
     441      var exprList = new List<ISymbolicExpressionTreeNode>();
     442      exprList.Add(ParseExpr(tokens));
     443      while (tokens.Peek().TokenType != TokenType.RightPar) {
     444        var comma = tokens.Dequeue();
     445        if (comma.TokenType != TokenType.Comma) throw new ArgumentException("expected ',' ");
     446        exprList.Add(ParseExpr(tokens));
     447      }
     448      return exprList.ToArray();
     449    }
    398450  }
    399451}
Note: See TracChangeset for help on using the changeset viewer.