out of order variables

50 views
Skip to first unread message

a12597

unread,
Dec 27, 2011, 6:08:29 AM12/27/11
to Jep Java Users
Hi,

i'm currently evaluating jep for a commercial project.

I'd like to know if the following is possible with Jep:

e.g.

Jep jep = new Jep();
jep.setAllowUndeclared(true);
jep.setAllowAssignment(true);
jep.addVariable("Var1", 1);
jep.addVariable("Var2", 2);
jep.addVariable("Var3", 3);
jep.parse("Var5 = Var4 + 1");
jep.parse("Var4 = Var1 + Var2 + Var3");

jep.evaluate(); // -> throws exception
System.out.println(jep.getVariableValue("Var5"));

Var5 depends on Var4 which is assigned afterward, is there a way for
Var5 to be initialized only after Var4 has been assigned?

thanks in advance
Roberto

Richard

unread,
Dec 28, 2011, 7:51:31 AM12/28/11
to Jep Java Users
Robert

Yes it should be possible. You will need one evaluate call for each
parse call so

Jep jep = new Jep();
jep.setAllowUndeclared(true);
jep.setAllowAssignment(true);
jep.addVariable("Var1", 1);
jep.addVariable("Var2", 2);
jep.addVariable("Var3", 3);

jep.parse("Var5 = Var4 + 1");
jep.evaluate(); // -> throws exception

jep.parse("Var4 = Var1 + Var2 + Var3");
jep.evaluate(); // -> throws exception

System.out.println(jep.getVariableValue("Var5"));

Evalute with no arguments will evaluate the last expression parsed.

You make what it explicit what you are evaluating

Node n1 = jep.parse("Var5 = Var4 + 1");
jep.evaluate(n1); // -> throws exception

Node n2 = jep.parse("Var4 = Var1 + Var2 + Var3");
jep.evaluate(n2); // -> throws exception

Hope that helps

Richard

robertointernet

unread,
Dec 29, 2011, 5:03:56 AM12/29/11
to Jep Java Users
Hi Richard,

thanks for the reply, but maybe I wasn't clear with my question

Node n1 = jep.parse("Var5 = Var4 + 1");
Node n2 = jep.parse("Var4 = Var1 + Var2 + Var3");
jep.evaluate(n1);
jep.evaluate(n2);

It will fail with the error not evaluate Var4: no value set for the
variable.
The code below will work

Node n1 = jep.parse("Var5 = Var4 + 1");
Node n2 = jep.parse("Var4 = Var1 + Var2 + Var3");
jep.evaluate(n2);
jep.evaluate(n1);

but if forces me to know the correct order of the variables.
What we're looking for is to randomly add variables and only at the
end evaluate everything and let Jep resolve the variables.

We have a workaround which involves recursively looking at the
formulas and looking up the variables but we wonder if there is a way
in Jep to do this (fantastic tool by the way)

best regards
Roberto

Richard Morris

unread,
Dec 30, 2011, 12:43:52 PM12/30/11
to jep-...@googlegroups.com
Roberto

Ah, I understand now. You will need to add some extra code to work out
the correct order to evaluate the expressions. You can use the
com.singularsys.jep.walkers.TreeAnalyzer to work out which variables
are contained in other expressions.
With this it is then possible to order the expressions for correct evaluation.

The first method below finds if one expression depends on another. The
second metod is a test which
uses a sorting algorithm to order the expressions. Its a little
inefficient and should really have some testing.


/**
* 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 testExpressionOrdering() throws ParseException, Exception {


Jep jep = new Jep();

// setup equations to be parsed
String[] eqns = new String[]{
"Var4 = Var1 + Var3",
"Var5 = Var4 + 1",
"Var3 = 3 * Var2"
};
// parse each expression
Node[] nodes = new Node[eqns.length];
for(int i=0;i<eqns.length;++i) {
nodes[i]=jep.parse(eqns[i]);
}

// build an array of dependancies
boolean[][] deps = new boolean[eqns.length][eqns.length];
for(int i=0;i<eqns.length;++i) {
for(int j=0;j<eqns.length;++j) {
if(i==j) continue;
if(dependsOn(nodes[i],nodes[j])) {
System.out.printf("\"%s\" depends on \"%s\"%n",
jep.toString(nodes[i]),jep.toString(nodes[j]));
deps[i][j]=true;
}
else {
System.out.printf("\"%s\" does not depends on \"%s\"%n",
jep.toString(nodes[i]),jep.toString(nodes[j]));
deps[i][j]=false;
}
}
}
System.out.println(Arrays.deepToString(deps));

int[] order = new int[eqns.length];
Arrays.fill(order, -1);
boolean[] done = new boolean[eqns.length];
Arrays.fill(done, false);

for(int loop=0;loop<eqns.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<eqns.length;++i) {
if(done[i]) continue;

boolean OK=true; // does anything depend on this
for(int j=0;j<eqns.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=eqns.length-1;i>=0;--i) {
jep.println(nodes[order[i]]);
jep.evaluate(nodes[order[i]]);
}
}

> --
> You received this message because you are subscribed to the Google Groups "Jep Java Users" group.
> To post to this group, send email to jep-...@googlegroups.com.
> To unsubscribe from this group, send email to jep-users+...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/jep-users?hl=en.
>

Reply all
Reply to author
Forward
0 new messages