Package jmathexpr.arithmetic.equation

Source Code of jmathexpr.arithmetic.equation.LinearEquation$AxpBeC$AdditionC

/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package jmathexpr.arithmetic.equation;

import jmathexpr.Constant;
import jmathexpr.Expression;
import jmathexpr.Precedence;
import jmathexpr.Variable;
import jmathexpr.arithmetic.ANumber;
import jmathexpr.arithmetic.Numbers;
import jmathexpr.arithmetic.Polynomial;
import jmathexpr.arithmetic.equation.rule.Fraction;
import jmathexpr.arithmetic.equation.rule.RuleMachine;
import jmathexpr.arithmetic.natural.Naturals;
import jmathexpr.arithmetic.op.Addition;
import jmathexpr.arithmetic.op.Division;
import jmathexpr.arithmetic.op.Multiplication;
import jmathexpr.arithmetic.op.Negation;
import jmathexpr.arithmetic.op.Subtraction;
import jmathexpr.arithmetic.op.Sum;
import jmathexpr.arithmetic.pattern.PolynomialTermPattern;
import jmathexpr.arithmetic.rule.AssociativeLaw;
import jmathexpr.arithmetic.rule.DistributiveLaw;
import jmathexpr.op.Operation;
import jmathexpr.relation.Equality;
import jmathexpr.set.Set;
import jmathexpr.util.pattern.ExpressionPattern;
import jmathexpr.util.rule.CompositeRule;
import jmathexpr.util.rule.SimpleRule;
import jmathexpr.util.rule.SubRule;

/**
* Linear equation in one unknown.
*
* @author Elemér Furka
*/
public class LinearEquation extends Equation {
   
    /**
     * Creates a new linear equation specifying the two sides of the equality.
     *
     * @param lhs left hand side of the equality
     * @param rhs right hand side of the equality
     * @param x the unknown in the equation
     */
    public LinearEquation(Expression lhs, Expression rhs, Variable x) {
        super(lhs, rhs, x);
    }

    /**
     * Creates a new linear equation instance using an existing equality.
     *
     * @param equality the equality to be transformed into an equation
     * @param x the unknown in the equation
     */
    public LinearEquation(Equality equality, Variable x) {
        this(equality.lhs(), equality.rhs(), x);
    }

    @Override
    protected LinearEquation create(Expression lhs, Expression rhs) {
        return new LinearEquation(lhs, rhs, x);
    }
   
    @Override
    public Set solve() throws EquationSolveException {
        rules = new RuleMachine(this);
       
        rules.addRule(new Fraction());
        rules.addRule(new DistributiveLaw());
        rules.addRule(new AssociativeLaw());
        rules.addRule(new VariableOnBothSides());
        rules.addRule(new AxpBeC());
        rules.addRule(new AxeB());

        Set result = rules.execute();
       
        result = check(result);
                       
        return result;
    }
   
    /**
     * Tests whether the given expression could be converted into a linear
     * equation in the given indeterminate.
     *
     * @param expr an arbitrary expression
     * @param x the indeterminate
     * @return true iff the given expression is an equation that only contains
     * linear terms
     */
    public static boolean isConvertible(Expression expr, Variable x) {
        if (!(expr instanceof Equality)) {
            return false;
        }
       
        Expression lhs = ((Equality) expr).lhs();
        Expression rhs = ((Equality) expr).rhs();
        boolean lhsIsLinear = isLinear(lhs, x);
        boolean rhsIsLinear = isLinear(rhs, x);
       
        return (lhsIsLinear && (rhs.isConstant() || rhsIsLinear))
                || (rhsIsLinear && (lhs.isConstant() || lhsIsLinear));
    }
   
    public static boolean isLinear(Expression expr, Variable x) {
        ExpressionPattern pattern = new PolynomialTermPattern(x, 1);
       
        if (pattern.matches(expr)) {
            return true;
        } else if (expr instanceof Negation) {
            return isLinear(((Negation) expr).getChild(), x);
        } else if (expr instanceof Division) {
            Expression lhs = ((Division) expr).lhs();
            Expression rhs = ((Division) expr).rhs();
           
            return rhs.isConstant() && isLinear(lhs, x);
        } else if (expr instanceof Operation
                && expr.getPrecedence() == Precedence.Addition) {
            boolean isLinear = false;
           
            for (Expression t : ((Operation) expr).operands()) {
                if (isLinear(t, x)) {
                    isLinear = true;
                } else if (!t.isConstant()) {
                    return false;
                }
            }
           
            return isLinear;
        } else if (expr instanceof Polynomial) {
            return ((Polynomial) expr).degree().equals(Naturals.one());
        }

        return false;
    }
   
    /**
     * The special case ax + b = cx + d -> b = (c-a)x + d or (a-c)x + b = d.
     */
    private class VariableOnBothSides extends SimpleRule {
       
        private final PolynomialTermPattern ax = new PolynomialTermPattern(x, 1);
        private final Constant b = Numbers.constant("b");
        private final PolynomialTermPattern cx = new PolynomialTermPattern(x, 1);
        private final Constant d = Numbers.constant("d");
       
        @Override
        public boolean matches(Expression expr) {
            target = expr;
           
            return new Equality(new Sum(ax, b), new Sum(cx, d)).matches(expr);
        }

        @Override
        public Expression apply() {
            ANumber ca = (ANumber) ax.coefficient();
            ANumber cc = (ANumber) cx.coefficient();
            ANumber coef = ca.lt(cc) ? ca : cc;

            if (coef.isNegative()) {
                coef = coef.negate();
               
                Expression cx = coef.isOne() ? x.evaluate() : new Multiplication(coef, x.evaluate());
               
                return new Equality(Sum.add(((Equality) target).lhs(), cx),
                    Sum.add(((Equality) target).rhs(), cx));
            } else {
                Expression cx = coef.isOne() ? x.evaluate() : new Multiplication(coef, x.evaluate());
               
                return new Equality(Sum.subtract(((Equality) target).lhs(), cx),
                    Sum.subtract(((Equality) target).rhs(), cx));
            }
        }
    }
   
    /**
     * The special case ax +- b = c.
     */
    private class AxpBeC extends CompositeRule {
       
        private final PolynomialTermPattern ax = new PolynomialTermPattern(x, 1);
        private final Constant b = Numbers.constant("b");
        private final Constant c = Numbers.constant("c");
       
        private AxpBeC() {
            super(false);
        }
       
        @Override
        public boolean matches(Expression expr) {
            target = expr;
           
            if ((rule = new AdditionC()).matches(expr)) return true;
            if ((rule = new SubtractionC()).matches(expr)) return true;
            if ((rule = new SubtractionX()).matches(expr)) return true;
           
            return false;
        }
       
        /**
         * ax + b = c  /-b
         */
        private class AdditionC extends SubRule {

            @Override
            public boolean matches(Expression expr) {
                return new Equality(new Addition(ax, b), c).matches(expr);
            }

            @Override
            public Expression apply() {
                ANumber term = (ANumber) b.hit();
               
                return new Equality(Sum.subtract(((Equality) target).lhs(), term),
                        Sum.subtract(((Equality) target).rhs(), term));
            }
        }
       
        /**
         * ax - b = c  /+b
         */
        private class SubtractionC extends SubRule {

            @Override
            public boolean matches(Expression expr) {
                return new Equality(new Subtraction(ax, b), c).matches(expr);
            }

            @Override
            public Expression apply() {
                Expression term = b.hit();
               
                return new Equality(Sum.add(((Equality) target).lhs(), term),
                        Sum.add(((Equality) target).rhs(), term));
            }
        }
       
        /**
         * b - ax = c  /+ax
         */
        private class SubtractionX extends SubRule {

            @Override
            public boolean matches(Expression expr) {
                return new Equality(new Subtraction(b, ax), c).matches(expr);
            }

            @Override
            public Expression apply() {
                Expression var = ax.hit();
               
                return new Equality(Sum.add(((Equality) target).lhs(), var),
                        Sum.add(((Equality) target).rhs(), var));
            }
        }
    }
   
    /**
     * The special case ax = b.
     */
    private class AxeB extends SimpleRule {
       
        private final Constant a = Numbers.constant("a");
        private final Constant b = Numbers.constant("b");
       
        @Override
        public boolean matches(Expression expr) {
            target = expr;
           
            Expression ax = new Multiplication(a, x);

            boolean matches = new Equality(ax, b).matches(expr) || new Equality(b, ax).matches(expr);
           
            // Don't match the case x = b (a = 1)
            matches = matches && !a.hit().equals(Naturals.one());

            return matches;
        }
       
        @Override
        public Expression apply() {
            Expression coef = a.hit();

            return new Equality(new Division(((Equality) target).lhs(), coef),
                    new Division(((Equality) target).rhs(), coef));
        }
    }
}
TOP

Related Classes of jmathexpr.arithmetic.equation.LinearEquation$AxpBeC$AdditionC

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.