Evaluation Path

52 views
Skip to first unread message

Craig Giordano

unread,
May 14, 2012, 2:45:17 PM5/14/12
to jep-...@googlegroups.com
Is there a way I can get the path through the node tree when Jep does a call to evaluate?

For example, if I have the following expression:

@IF({Z}=1,@IF({Y}=2,@IF({X}=3,"A","B"),@IF({W}=4,"C","D")),@IF({V}=5,@IF({U}=6,"E","F"),@IF({T}=7,"G","H")))

that evaluates to "H", can I get a reference to the node that is the answer or a path leading to that node?  My use case is that I would like to mark up the expression after evaluation to show which path was followed to find the answer.  For example, I would emit the following to show the path to the answer.

<FONT COLOR="red">@IF({Z}=1.0</FONT>,@IF({Y}=2.0,@IF({X}=3.0,"A","B"),@IF({W}=4.0,"C","D")),<FONT COLOR="red">@IF({V}=5.0</FONT>,@IF({U}=6.0,"E","F"),<FONT COLOR="red">@IF({T}=7.0</FONT>,"G",<FONT COLOR="red">"H"</FONT>)))

which would then be displayed as:

@IF({Z}=1,@IF({Y}=2,@IF({X}=3,"A","B"),@IF({W}=4,"C","D")),@IF({V}=5,@IF({U}=6,"E","F"),@IF({T}=7,"G","H")))

Thanks,
Craig

Richard

unread,
May 15, 2012, 4:25:51 PM5/15/12
to Jep Java Users
Craig,

The easiest way to achieve this is to sub class FastEvaluator to
create a method which records each node as its is evaluated

class PathEvaluator extends FastEvaluator {

@Override
protected Object nodeAccept(Node node) throws EvaluationException {
System.out.println("Visit "+node.toString());
return super.nodeAccept(node);
}
}

This overrides an undocumented method of that evaluator which is
called for each node evaluated. This method simply prints the nodes as
they are visited and then calls the superclass method to perform the
evaluation. You would use

@Test
public void testEvaluationPath() throws JepException {
String s = "if(Z==1," +
"if(Y==2,if(X==3,\"A\",\"B\"),if(W==4,\"C\",\"D\"))," +
"if(V==5,if(U==6,\"E\",\"F\"),if(T==7,\"G\",\"H\")))";
// Create the evaluator
Evaluator ev = new PathEvaluator();
// Set up jep using this evaluator
Jep jep = new Jep(ev);
jep.addVariable("Z", 1);
jep.addVariable("Y", 2);
jep.addVariable("X", 3);
jep.addVariable("W", 1);
jep.addVariable("U", 1);
jep.addVariable("V", 1);
jep.addVariable("T", 1);
// Parse and evaluate the equation
Node n = jep.parse(s);
Object res = jep.evaluate(n);
System.out.println("Result: "+res);
}

More sophisticated actions are possible in that method. You could use
the Node.setHook() methods to annotate nodes as they are visited.

Richard

On May 14, 7:45 pm, Craig Giordano <craig.giord...@gmail.com> wrote:
> Is there a way I can get the path through the node tree when Jep does a
> call to evaluate?
>
> For example, if I have the following expression:
>
> @IF({Z}=1,@IF({Y}=2,@IF({X}=3,"A","B"),@IF({W}=4,"C","D")),@IF({V}=5,@IF({U }=6,"E","F"),@IF({T}=7,"G","H")))
>
> that evaluates to "H", can I get a reference to the node that is the answer
> or a path leading to that node?  My use case is that I would like to mark
> up the expression after evaluation to show which path was followed to find
> the answer.  For example, I would emit the following to show the path to
> the answer.
>
> <FONT
> COLOR="red">@IF({Z}=1.0</FONT>,@IF({Y}=2.0,@IF({X}=3.0,"A","B"),@IF({W}=4.0 ,"C","D")),<FONT

Craig Giordano

unread,
May 16, 2012, 9:34:32 AM5/16/12
to jep-...@googlegroups.com
Richard,

I am following your advice except I am just keeping a reference to the last node evaluated.  My subclass looks like this:

public class TraceEvaluator extends FastEvaluator {

    private Node lastNode;

    public Node getLastNode() {
        return lastNode;

    }

    @Override
    protected Object nodeAccept(Node node) throws EvaluationException {
        lastNode = node;
        return super.nodeAccept(node);
    }
}

After Jep evaluates the root node, I have a reference to the last node.  I then follow the parents of the last node to create the path.  Lastly, I walk the parse tree in my emitter, marking up only those nodes that are on the path.

Thanks,
Craig
Reply all
Reply to author
Forward
0 new messages