Class ExpressionCleaner

java.lang.Object
com.singularsys.extensions.xjep.ExpressionCleaner
All Implemented Interfaces:
GenericVisitor<Node,Void,ParseException>, JepComponent, Serializable
Direct Known Subclasses:
DExpressionCleaner

public class ExpressionCleaner extends Object implements GenericVisitor<Node,Void,ParseException>, JepComponent
Cleans up expressions, removing redundant parts. To use
 Jep j = new Jep();
 TreeUtils tu = new TreeUtils(jep.getNumberFactory());
 ExpressionCleaner sv = new ExpressionCleaner(jep, tu);
 
 Node in = jep.parse("1*x^1+0");
 Node out = sv.clean(in);
 

Note this visitor works in-place.

Since Jep 4.0/Extensions 2.1 respects the DirtyFunction interface so functions like rand() are no cleaned.

Since Jep 4.1, extension 2.2, this now implements GenericVisitor some method signatures have changed to be more specific.

See Also:
  • Constructor Details

    • ExpressionCleaner

      public ExpressionCleaner()
      Constructor to use when used with Jep.setComponent(JepComponent component). The reference to the jep instance and TreeUtils are found in init(Jep).
    • ExpressionCleaner

      public ExpressionCleaner(Jep j, TreeUtils tu)
      Constructor with explicit Jep and TreeUtils instances. Can be used in a standalone context.
      Parameters:
      j -
      tu - TreeUtils class to use
  • Method Details

    • getLightWeightInstance

      public JepComponent getLightWeightInstance()
      Description copied from interface: JepComponent
      Gets a light-weight instance suitable for using in multiple threads.
      Specified by:
      getLightWeightInstance in interface JepComponent
      Returns:
      either a new instance, null or 'this'.
    • init

      public void init(Jep j)
      Description copied from interface: JepComponent
      Initialize the component. This method is called whenever a component is added to Jep. Hence, it allows components to keep track of the other components they may rely on.
      Specified by:
      init in interface JepComponent
      Parameters:
      j - the current Jep instance
    • clean

      public Node clean(Node node) throws ParseException
      Main entry point. Cleans the node in place.
      Parameters:
      node - the base of the tree which will be modified.
      Returns:
      simplified version of the expression tree, no necessarily the same object as the input.
      Throws:
      ParseException
    • cleanBuildOperatorNode

      public Node cleanBuildOperatorNode(Operator op, Node lhs, Node rhs) throws ParseException
      First create a new node and then clean it.
      Throws:
      ParseException
    • cleanBuildOperatorNode

      public Node cleanBuildOperatorNode(Operator op, Node node) throws ParseException
      Throws:
      ParseException
    • cleanOp

      public Node cleanOp(Node node, Node... children) throws ParseException
      simplifies operators, does not descend into children
      Throws:
      ParseException
    • cleanOp

      public Node cleanOp(Operator op, Node... children) throws ParseException
      Attempt to clean an operator.
      Parameters:
      op -
      children -
      Returns:
      a simplified expression or null if it could be simplified.
      Throws:
      ParseException
    • cleanTriple

      public Node cleanTriple(Operator op, Node lhs, Node rhs) throws ParseException
      Cleans expressions like 2+(3+x) or (2+x)+3.
      • 2 + ~( 3 + ~x ) -> (2+~3) + ~~x
      • 2 * (3 + ~x) -> (2 * 3) + ~(2 @ x)
      • 2 + ~( x + ~3 ) -> (2 + ~~3) + ~x
      • 2 * (x + ~3) -> (2 * x) + ~(2 * 3)
      • (2 + ~x) + ~3 -> (2 + ~3) + ~x
      • (2 + ~x) * 3 --> (2*3) +~ (x*3)
      • (x + ~2) + !3 -> x + (~2 + !3) -> x + ~(2+~!3)
      • (x*2)*3 -> x*(2*3), (x/2)*3 -> x/(2/3)
      • (x*2)/3 -> x*(2/3), (x/2)/3 -> x/(2*3)
      • (x + ~2) * 3 -> (x*3) + ~(2*3)
      • x * (y * z) -> (x * y) * z where * is an associative left binding operator
      • (x ! y) ! z -> x ! (y ! z) where ! is an associative right binding operator
      • (x * y) * 2 -> (2 * x) * y
      • (x-y)+z -> (x+z)-y
      • (x/y)*z -> (x*z)/y
      Parameters:
      op - the root operator
      lhs - the left-hand side node
      rhs - the right-hand side node
      Returns:
      null if no rewrite happens or top node or top node of new tree.
      Throws:
      ParseException
    • cleanAdd

      public Node cleanAdd(Node lhs, Node rhs) throws ParseException
      Cleans an addition. Performs the following rules
       0+x -> x
       x+0 -> x
       m+n -> (m+n) where m,n are numbers
       x - (-2) -> x + 2 for any negative number -2
       x + (-2) -> x - 2 for any negative number -2
       2 +/- ( 3 +/- x ) ->  (2 +/- 3 ) +/- x and similar
       
      Throws:
      ParseException
    • cleanSubtract

      public Node cleanSubtract(Node lhs, Node rhs) throws ParseException
      Cleans a subtraction. Performs the following rules
       +Infinity-x -> +Infinity 
       -Infinity-x -> -Infinity 
       x - +Infinity -> -Infinity 
       x - -Infinity -> +Infinity 
       0-x -> 0-x
       x-0 -> x
       m-n -> (m-n) where m,n are numbers
       x - (-2) -> x + 2 for any negative number -2
       x + (-2) -> x - 2 for any negative number -2
       2 +/- ( 3 +/- x ) ->  (2 +/- 3 ) +/- x and similar
       
      Parameters:
      lhs - the left-hand side
      rhs - the right-hand side
      Throws:
      ParseException
    • cleanMultiply

      public Node cleanMultiply(Node child1, Node child2) throws ParseException
      Cleans a multiplication.
       0 * Inf -> NaN
       0 * x -> 0
       x * 0 -> 0
       1 * x -> x
       x * 1 -> x
       Inf * x -> Inf
       x * Inf -> Inf
       2 * ( 3 * x) -> (2*3) * x
       2 * (-x) -> -2 * x
       and similar.
       
      Throws:
      ParseException
    • cleanDivide

      public Node cleanDivide(Node child1, Node child2) throws ParseException
      Cleans a division.
       0/0 -> NaN
       0/Inf -> Inf
       0/x -> Inf
       x/0 -> Inf
       x/1 -> x
       Inf / x -> Inf
       x / Inf -> 0
       2 / ( 3 * x) -> (2/3) / x
       2 / ( x * 3) -> (2/3) / x
       2 / ( 3 / x) -> (2/3) * x
       2 / ( x / 3) -> (2*3) / x
       (2 * x) / 3 -> (2/3) * x
       (x * 2) / 3 -> x * (2/3)
       (2 / x) / 3 -> (2/3) / x
       (x / 2) / 3 -> x / (2*3)
       
      Throws:
      ParseException
    • cleanPower

      public Node cleanPower(Node child1, Node child2) throws ParseException
      Simplify a power.
       x^0 -> 1
       x^1 -> x
       0^0 -> NaN
       0^x -> 0
       1^x -> 1
       
      Throws:
      ParseException
    • cleanUMinus

      public Node cleanUMinus(Node child) throws ParseException
      Throws:
      ParseException
    • visit

      public Node visit(ASTOpNode node, Void data) throws ParseException
      Description copied from interface: GenericVisitor
      Visit an operator node
      Specified by:
      visit in interface GenericVisitor<Node,Void,ParseException>
      Parameters:
      node - current node
      data - context data
      Returns:
      the result of visiting the node
      Throws:
      ParseException
    • visit

      public Node visit(ASTFunNode node, Void data) throws ParseException
      Description copied from interface: GenericVisitor
      Visit a function node
      Specified by:
      visit in interface GenericVisitor<Node,Void,ParseException>
      Parameters:
      node - current node
      data - context data
      Returns:
      the result of visiting the node
      Throws:
      ParseException
    • visit

      public Node visit(ASTConstant node, Void data) throws ParseException
      Description copied from interface: GenericVisitor
      Visit a constant node
      Specified by:
      visit in interface GenericVisitor<Node,Void,ParseException>
      Parameters:
      node - current node
      data - context data
      Returns:
      the result of visiting the node
      Throws:
      ParseException
    • visit

      public Node visit(ASTVarNode node, Void data) throws ParseException
      Description copied from interface: GenericVisitor
      Visit a variable node
      Specified by:
      visit in interface GenericVisitor<Node,Void,ParseException>
      Parameters:
      node - current node
      data - context data
      Returns:
      the result of visiting the node
      Throws:
      ParseException
    • makeException

      public ParseException makeException(String message)
      Description copied from interface: GenericVisitor
      Create an Exception of the correct type. A typical implementation is
      @Override
      public JepException makeException(String message) {
       return new JepException(message);
      }
      
      Specified by:
      makeException in interface GenericVisitor<Node,Void,ParseException>
      Parameters:
      message - error message
      Returns:
      an Exception