Exemplo n.º 1
0
        private static ISymbolicExpressionTreeNode CreateConstant(double v)
        {
            var constNode = (ConstantTreeNode)constantSy.CreateTreeNode();

            constNode.Value = v;
            return(constNode);
        }
 private ISymbolicExpressionTreeNode ParseSexp(Queue <Token> tokens)
 {
     if (tokens.Peek().Symbol == TokenSymbol.LPAR)
     {
         ISymbolicExpressionTreeNode tree;
         Expect(Token.LPAR, tokens);
         if (tokens.Peek().StringValue.StartsWith(VARSTART))
         {
             tree = ParseVariable(tokens);
         }
         else if (tokens.Peek().StringValue.StartsWith(LAGGEDVARSTART))
         {
             tree = ParseLaggedVariable(tokens);
         }
         else if (tokens.Peek().StringValue.StartsWith(TIMELAGSTART))
         {
             tree = ParseTimeLag(tokens);
             tree.AddSubtree(ParseSexp(tokens));
         }
         else if (tokens.Peek().StringValue.StartsWith(INTEGRALSTART))
         {
             tree = ParseIntegral(tokens);
             tree.AddSubtree(ParseSexp(tokens));
         }
         else if (tokens.Peek().StringValue.StartsWith(DEFUNSTART))
         {
             tree = ParseDefun(tokens);
             while (!tokens.Peek().Equals(Token.RPAR))
             {
                 tree.AddSubtree(ParseSexp(tokens));
             }
         }
         else if (tokens.Peek().StringValue.StartsWith(ARGSTART))
         {
             tree = ParseArgument(tokens);
         }
         else if (tokens.Peek().StringValue.StartsWith(INVOKESTART))
         {
             tree = ParseInvoke(tokens);
             while (!tokens.Peek().Equals(Token.RPAR))
             {
                 tree.AddSubtree(ParseSexp(tokens));
             }
         }
         else if (tokens.Peek().StringValue.StartsWith("FACTOR"))
         {
             tree = ParseFactor(tokens);
         }
         else if (tokens.Peek().StringValue.StartsWith("BINFACTOR"))
         {
             tree = ParseBinaryFactor(tokens);
         }
         else
         {
             Token curToken = tokens.Dequeue();
             tree = CreateTree(curToken);
             while (!tokens.Peek().Equals(Token.RPAR))
             {
                 tree.AddSubtree(ParseSexp(tokens));
             }
         }
         Expect(Token.RPAR, tokens);
         return(tree);
     }
     else if (tokens.Peek().Symbol == TokenSymbol.NUMBER)
     {
         ConstantTreeNode t = (ConstantTreeNode)constant.CreateTreeNode();
         t.Value = tokens.Dequeue().DoubleValue;
         return(t);
     }
     else
     {
         throw new FormatException("Expected function or constant symbol");
     }
 }
Exemplo n.º 3
0
        /// Expr          = ['-' | '+'] Term { '+' Term | '-' Term }
        private ISymbolicExpressionTreeNode ParseExpr(Queue <Token> tokens)
        {
            var  next            = tokens.Peek();
            var  posTerms        = new List <ISymbolicExpressionTreeNode>();
            var  negTerms        = new List <ISymbolicExpressionTreeNode>();
            bool negateFirstTerm = false;

            if (next.TokenType == TokenType.Operator && (next.strVal == "+" || next.strVal == "-"))
            {
                tokens.Dequeue();
                if (next.strVal == "-")
                {
                    negateFirstTerm = true;
                }
            }
            var t = ParseTerm(tokens);

            if (negateFirstTerm)
            {
                negTerms.Add(t);
            }
            else
            {
                posTerms.Add(t);
            }

            next = tokens.Peek();
            while (next.strVal == "+" || next.strVal == "-")
            {
                switch (next.strVal)
                {
                case "+": {
                    tokens.Dequeue();

                    var term = ParseTerm(tokens);
                    posTerms.Add(term);
                    break;
                }

                case "-": {
                    tokens.Dequeue();
                    var term = ParseTerm(tokens);
                    negTerms.Add(term);
                    break;
                }
                }
                next = tokens.Peek();
            }

            var sum = GetSymbol("+").CreateTreeNode();

            foreach (var posTerm in posTerms)
            {
                sum.AddSubtree(posTerm);
            }
            if (negTerms.Any())
            {
                if (negTerms.Count == 1)
                {
                    var sub = GetSymbol("-").CreateTreeNode();
                    sub.AddSubtree(negTerms.Single());
                    sum.AddSubtree(sub);
                }
                else
                {
                    var sumNeg = GetSymbol("+").CreateTreeNode();
                    foreach (var negTerm in negTerms)
                    {
                        sumNeg.AddSubtree(negTerm);
                    }

                    var constNode = (ConstantTreeNode)constant.CreateTreeNode();
                    constNode.Value = -1.0;
                    var prod = GetSymbol("*").CreateTreeNode();
                    prod.AddSubtree(constNode);
                    prod.AddSubtree(sumNeg);

                    sum.AddSubtree(prod);
                }
            }
            if (sum.SubtreeCount == 1)
            {
                return(sum.Subtrees.First());
            }
            else
            {
                return(sum);
            }
        }
Exemplo n.º 4
0
        // simplify multiplications by reducing constants and div terms
        public static void SimplifyMultiplication(ref HashNode <ISymbolicExpressionTreeNode>[] nodes, int i)
        {
            var node     = nodes[i];
            var children = nodes.IterateChildren(i);

            for (int j = 0; j < children.Length; ++j)
            {
                var c     = children[j];
                var child = nodes[c];

                if (!child.Enabled)
                {
                    continue;
                }

                var symbol = child.Data.Symbol;
                if (child.Data is ConstantTreeNode firstConst)
                {
                    // fold sibling constant nodes into the first constant
                    for (int k = j + 1; k < children.Length; ++k)
                    {
                        var sibling = nodes[children[k]];
                        if (sibling.Data is ConstantTreeNode otherConst)
                        {
                            sibling.Enabled = false;
                            node.Arity--;
                            firstConst.Value *= otherConst.Value;
                        }
                        else
                        {
                            break;
                        }
                    }
                }
                else if (child.Data is VariableTreeNode variable)
                {
                    // fold sibling constant nodes into the variable weight
                    for (int k = j + 1; k < children.Length; ++k)
                    {
                        var sibling = nodes[children[k]];
                        if (sibling.Data is ConstantTreeNode constantNode)
                        {
                            sibling.Enabled = false;
                            node.Arity--;
                            variable.Weight *= constantNode.Value;
                        }
                        else
                        {
                            break;
                        }
                    }
                }
                else if (symbol is Division)
                {
                    // 1/x is expressed as div(x) (with a single child)
                    // we assume division always has arity 1 or 2
                    var d           = child.Arity == 1 ? c - 1 : c - nodes[c - 1].Size - 2;
                    var denominator = nodes[d];

                    // iterate children of node i to see if any of them matches the denominator of div node c
                    for (int k = 0; k < children.Length; ++k)
                    {
                        var sibling = nodes[children[k]];
                        if (sibling.Enabled && sibling == denominator)
                        {
                            nodes.SetEnabled(children[j], false); // disable the div subtree
                            nodes.SetEnabled(children[k], false); // disable the sibling matching the denominator

                            node.Arity -= 2;                      // matching child + division node
                            break;
                        }
                    }
                }

                if (node.Arity == 0) // if everything is simplified this node becomes constant
                {
                    var constantTreeNode = constant.CreateTreeNode <ConstantTreeNode>();
                    constantTreeNode.Value = 1;
                    nodes[i] = constantTreeNode.ToHashNode();
                }
                else if (node.Arity == 1) // when i have only 1 arg left i can skip this node
                {
                    node.Enabled = false;
                }
            }
        }