Search in sources :

Example 1 with NumberNode

use of org.matheclipse.parser.client.ast.NumberNode in project symja_android_library by axkr.

the class DoubleEvaluator method derivative.

/**
	 * 
	 * TODO: add more derivation rules
	 * 
	 * @param node
	 * @param var
	 * @return
	 */
public ASTNode derivative(final ASTNode node, SymbolNode var) {
    if (node.isFree(var)) {
        return new DoubleNode(0.0);
    }
    if (node instanceof FunctionNode) {
        FunctionNode f = (FunctionNode) node;
        if (f.size() > 1 && f.getNode(0) instanceof SymbolNode) {
            SymbolNode head = (SymbolNode) f.getNode(0);
            if (f.size() == 2) {
                ASTNode arg1Derived = derivative(f.getNode(1), var);
                if (isSymbol(head, "Exp")) {
                    FunctionNode fun = new FunctionNode(fASTFactory.createSymbol("Exp"));
                    fun.add(f.getNode(1));
                    return getDerivativeResult(arg1Derived, fun);
                }
                if (isSymbol(head, "Cos")) {
                    FunctionNode fun = new FunctionNode(fASTFactory.createSymbol("Times"));
                    fun.add(new DoubleNode(-1.0));
                    fun.add(new FunctionNode(fASTFactory.createSymbol("Cos"), f.getNode(1)));
                    return getDerivativeResult(arg1Derived, fun);
                }
                if (isSymbol(head, "Sin")) {
                    FunctionNode fun = new FunctionNode(fASTFactory.createSymbol("Cos"));
                    fun.add(f.getNode(1));
                    return getDerivativeResult(arg1Derived, fun);
                }
            } else if (f.size() == 3 && isSymbol(head, "Power")) {
                if (f.get(2).isFree(var)) {
                    // derive x^r
                    ASTNode arg1Derived = derivative(f.getNode(1), var);
                    // (r-1)
                    FunctionNode exponent = fASTFactory.createFunction(fASTFactory.createSymbol("Plus"), new DoubleNode(-1.0), f.get(2));
                    // r*x^(r-1)
                    FunctionNode fun = fASTFactory.createFunction(fASTFactory.createSymbol("Times"), f.get(2), fASTFactory.createFunction(fASTFactory.createSymbol("Power"), f.get(1), exponent));
                    return getDerivativeResult(arg1Derived, fun);
                }
                if (f.get(1).isFree(var)) {
                    // derive a^x
                    ASTNode arg2Derived = derivative(f.getNode(2), var);
                    // log(a) * a^x
                    FunctionNode fun = fASTFactory.createFunction(fASTFactory.createSymbol("Times"), fASTFactory.createFunction(fASTFactory.createSymbol("Log"), f.get(1)), f);
                    return getDerivativeResult(arg2Derived, fun);
                }
            } else {
                if (isSymbol(head, "Plus")) {
                    FunctionNode result = new FunctionNode(f.getNode(0));
                    for (int i = 1; i < f.size(); i++) {
                        ASTNode deriv = derivative(f.getNode(i), var);
                        if (!deriv.equals(new DoubleNode(0.0))) {
                            result.add(deriv);
                        }
                    }
                    return result;
                }
                if (isSymbol(head, "Times")) {
                    FunctionNode plusResult = new FunctionNode(fASTFactory.createSymbol("Plus"));
                    for (int i = 1; i < f.size(); i++) {
                        FunctionNode timesResult = new FunctionNode(f.getNode(0));
                        boolean valid = true;
                        for (int j = 1; j < f.size(); j++) {
                            if (j == i) {
                                ASTNode deriv = derivative(f.getNode(j), var);
                                if (deriv.equals(new DoubleNode(0.0))) {
                                    valid = false;
                                } else {
                                    timesResult.add(deriv);
                                }
                            } else {
                                timesResult.add(f.getNode(j));
                            }
                        }
                        if (valid) {
                            plusResult.add(timesResult);
                        }
                    }
                    return plusResult;
                }
            }
        }
        return new FunctionNode(new SymbolNode("D"), node, var);
    // return evaluateFunction((FunctionNode) node);
    }
    if (node instanceof SymbolNode) {
        if (isSymbol((SymbolNode) node, var)) {
            return new DoubleNode(1.0);
        }
        IDoubleValue v = fVariableMap.get(node.toString());
        if (v != null) {
            return new DoubleNode(0.0);
        }
        Double dbl = SYMBOL_DOUBLE_MAP.get(node.toString());
        if (dbl != null) {
            return new DoubleNode(0.0);
        }
        return new DoubleNode(0.0);
    } else if (node instanceof NumberNode) {
        return new DoubleNode(0.0);
    }
    throw new ArithmeticMathException("EvalDouble#evaluate(ASTNode) not possible for: " + node.toString());
}
Also used : SymbolNode(org.matheclipse.parser.client.ast.SymbolNode) ArithmeticMathException(org.matheclipse.parser.client.math.ArithmeticMathException) NumberNode(org.matheclipse.parser.client.ast.NumberNode) FunctionNode(org.matheclipse.parser.client.ast.FunctionNode) ASTNode(org.matheclipse.parser.client.ast.ASTNode)

Example 2 with NumberNode

use of org.matheclipse.parser.client.ast.NumberNode in project symja_android_library by axkr.

the class Parser method parsePrimary.

private ASTNode parsePrimary() {
    if (fToken == TT_OPERATOR) {
        if (";;".equals(fOperatorString)) {
            FunctionNode function = fFactory.createFunction(fFactory.createSymbol(IConstantOperators.Span));
            function.add(fFactory.createInteger(1));
            getNextToken();
            if (fToken == TT_COMMA || fToken == TT_ARGUMENTS_CLOSE || fToken == TT_PRECEDENCE_CLOSE) {
                function.add(fFactory.createSymbol(IConstantOperators.All));
                return function;
            }
            function.add(parsePrimary());
            if (fToken == TT_OPERATOR && ";;".equals(fOperatorString)) {
                function.add(fFactory.createSymbol(IConstantOperators.All));
                getNextToken();
            }
            return function;
        }
        if (".".equals(fOperatorString)) {
            fCurrentChar = '.';
            return getNumber(false);
        }
        final PrefixOperator prefixOperator = determinePrefixOperator();
        if (prefixOperator != null) {
            getNextToken();
            final ASTNode temp = parseLookaheadOperator(prefixOperator.getPrecedence());
            if ("PreMinus".equals(prefixOperator.getFunctionName()) && temp instanceof NumberNode) {
                // special cases for negative numbers
                ((NumberNode) temp).toggleSign();
                return temp;
            }
            return prefixOperator.createFunction(fFactory, temp);
        }
        throwSyntaxError("Operator: " + fOperatorString + " is no prefix operator.");
    }
    return getPart();
}
Also used : PrefixOperator(org.matheclipse.parser.client.operator.PrefixOperator) NumberNode(org.matheclipse.parser.client.ast.NumberNode) FunctionNode(org.matheclipse.parser.client.ast.FunctionNode) ASTNode(org.matheclipse.parser.client.ast.ASTNode)

Example 3 with NumberNode

use of org.matheclipse.parser.client.ast.NumberNode in project symja_android_library by axkr.

the class DoubleEvaluator method optimizeFunction.

/**
	 * Optimize an already parsed in <code>functionNode</code> into an
	 * <code>ASTNode</code>.
	 * 
	 * @param functionNode
	 * @return
	 * 
	 */
public ASTNode optimizeFunction(final FunctionNode functionNode) {
    if (functionNode.size() > 0) {
        boolean doubleOnly = true;
        ASTNode node;
        for (int i = 1; i < functionNode.size(); i++) {
            node = functionNode.getNode(i);
            if (node instanceof NumberNode) {
                functionNode.set(i, new DoubleNode(((NumberNode) functionNode.getNode(i)).doubleValue()));
            } else if (functionNode.getNode(i) instanceof FunctionNode) {
                ASTNode optNode = optimizeFunction((FunctionNode) functionNode.getNode(i));
                if (!(optNode instanceof DoubleNode)) {
                    doubleOnly = false;
                }
                functionNode.set(i, optNode);
            } else if (node instanceof SymbolNode) {
                Double dbl = SYMBOL_DOUBLE_MAP.get(node.toString());
                if (dbl != null) {
                    functionNode.set(i, new DoubleNode(dbl.doubleValue()));
                } else {
                    doubleOnly = false;
                }
            } else {
                doubleOnly = false;
            }
        }
        if (doubleOnly) {
            try {
                return new DoubleNode(evaluateFunction(functionNode));
            } catch (Exception e) {
            }
        }
    }
    return functionNode;
}
Also used : SymbolNode(org.matheclipse.parser.client.ast.SymbolNode) NumberNode(org.matheclipse.parser.client.ast.NumberNode) ASTNode(org.matheclipse.parser.client.ast.ASTNode) FunctionNode(org.matheclipse.parser.client.ast.FunctionNode) ArithmeticMathException(org.matheclipse.parser.client.math.ArithmeticMathException)

Aggregations

ASTNode (org.matheclipse.parser.client.ast.ASTNode)3 FunctionNode (org.matheclipse.parser.client.ast.FunctionNode)3 NumberNode (org.matheclipse.parser.client.ast.NumberNode)3 SymbolNode (org.matheclipse.parser.client.ast.SymbolNode)2 ArithmeticMathException (org.matheclipse.parser.client.math.ArithmeticMathException)2 PrefixOperator (org.matheclipse.parser.client.operator.PrefixOperator)1