Rohan
On Mar 26, 5:57 pm, Rohan <
rohan...@gmail.com> wrote:
> Hi All,
>
> I have multiple expressions that need to be parsed and evaluated and I
> see the example athttp://
www.singularsys.com/jep/doc/html/usage.html#multieqn
> to understand how Jep handles multi expressions. My questions are
>
> Question 1 :
> Can I parse my multiple expressions only once initially and evaluate
> them multiple times using the solution specified with
> jep.initMultiParse(s); and jep.continueParsing();
> I have looked at
> the documentation and and have not found any possible solution using
> the current API. Is there any way I can get an Iterator over the Nodes
> parsed in this Jep instance, so that I can evaluate the parsed nodes
> without having to parse them again using initMultiParse(s)?
Yes you can evaluate many equations easily. It may be easiest if you
store the results of parsing in a list
Jep jep = new Jep();
// setup equations to be parsed
String eqns =
"x=5;"+
"y=6;"+
"z=x^2-y^2;"+
"w=z/(x-y);"+
"v=z/(x+y);";
List<Node> nodes = new ArrayList<Node>();
jep.initMultiParse(eqns);
// parse each expression
Node node;
while((node = jep.continueParsing())!=null) {
nodes.add(node);
}
// Now evaluate them in turn
for(Node n:nodes) {
Object res = jep.evaluate(n);
System.out.print("Equation:\t");
jep.println(n);
System.out.println("Result:\t"+res);
}
The evaluation loop can be run as many times as you want. You can use
jep.addVariable(name, value)
to change the values of variables in each loop.
> If the answer to the above questions is a 'No', I will use the
> solution which keeps track of the Nodes external to the Jep instance
> and evaluate them as needed.
> Question 2:
> Consider the following example
>
> Jep jep = new Jep();
> try {
> jep.addVariable("x",3);
> Node n1 = jep.parse("y=x^2");
> Node n2 = jep.parse("z=x+y");
>
> Object value2 = jep.evaluate(n2);
> Object value1 = jep.evaluate(n1);}
>
> catch(JepException e) { System.out.println(e.getMessage)}
>
> This Throws a JepException "Could not evaluate y: no value set for
> the variable. See
> com.singularsys.jep.standard.FastEvaluator.setTrapNullValues(boolean)."
>
> Is there a way to handle such a scenario where the order of
> expressions being evaluated is not controllable , but all the
> expressios are parsed before the evaluation begins. i.e. the evaluator
> should have access to all expressions irrespective of the evaluation
> order and should be able get the definition and hence the evaluation
> of y in the case of above example.
>
> Best,
> Rohan
This is very similar to the "out of order variables" thread in the
group archive
http://groups.google.com/group/jep-users/browse_thread/thread/3073eb988a6a2523?hl=en
It takes a bit of work using the TreeAnalyzer to work out the correct
order of evaluation:
/**
* Returns true if n1 depends on n2. That is if one of the
variables on the
* rhs of n1 is the lhs variable of n2.
*/
boolean dependsOn(Node n1,Node n2) throws JepException {
TreeAnalyzer ta = new TreeAnalyzer(n1.jjtGetChild(1));
List<String> n1rhs = Arrays.asList(ta.getVariableNames());
String n2lhs = n2.jjtGetChild(0).getName();
return n1rhs.contains(n2lhs);
}
/**
* Tests use of TreeAnalyzer to work out the order of
expressions.
* @throws ParseException
* @throws Exception
*/
@Test
public void testExpressionOrderingMultiLine() throws
ParseException, Exception {
Jep jep = new Jep();
// setup equations to be parsed
String eqns =
"Var4 = Var1 + Var3;"+
"Var5 = Var4 + 1;"+
"Var3 = 3 * Var2;";
List<Node> nodes = new ArrayList<Node>();
jep.initMultiParse(eqns);
// parse each expression
Node node;
while((node = jep.continueParsing())!=null) {
nodes.add(node);
}
for(Node n:nodes) {
jep.println(n);
}
int length = nodes.size();
// build an array of dependancies
boolean[][] deps = new boolean[length][length];
for(int i=0;i<length;++i) {
for(int j=0;j<length;++j) {
if(i==j) continue;
if(dependsOn(nodes.get(i),nodes.get(j))) {
System.out.printf("\"%s\" depends on \"%s\"%n",
jep.toString(nodes.get(i)),jep.toString(nodes.get(j)));
deps[i][j]=true;
}
else {
System.out.printf("\"%s\" does not depends on \"%s\"%n",
jep.toString(nodes.get(i)),jep.toString(nodes.get(j)));
deps[i][j]=false;
}
}
}
System.out.println(Arrays.deepToString(deps));
int[] order = new int[length];
Arrays.fill(order, -1);
boolean[] done = new boolean[length];
Arrays.fill(done, false);
for(int loop=0;loop<length;++loop) {
// find an expression A for which (B dep A) is false for
all other B
// exclude those which have already been done
for(int i=0;i<length;++i) {
if(done[i]) continue;
boolean OK=true; // does anything depend on this
for(int j=0;j<length;++j) {
if(done[j]) continue;
if(i==j) continue;
// something depends on this
if(deps[j][i]) OK=false;
}
if(OK) {
order[loop] = i;
done[i] = true;
break;
}
}
if(order[loop]==-1) {
System.out.println("nothing found");
}
}
System.out.println(Arrays.toString(order));
System.out.println(Arrays.toString(done));
jep.addVariable("Var1",1.0);
jep.addVariable("Var2",2.0);
for(int i=length-1;i>=0;--i) {
jep.println(nodes.get(order[i]));
jep.evaluate(nodes.get(order[i]));
}
}
You might be able to modify the code to reorder the list.
Hope that helps
Richards