package nars.operator.misc;
import java.util.List;
import nars.storage.Memory;
import nars.io.Texts;
import static nars.io.Texts.unescape;
import nars.language.Inheritance;
import nars.language.Product;
import nars.language.Term;
import nars.operator.SynchronousFunctionOperator;
import org.encog.ml.prg.EncogProgram;
import org.encog.ml.prg.EncogProgramContext;
import org.encog.ml.prg.ProgramNode;
import org.encog.ml.prg.expvalue.ExpressionValue;
import org.encog.ml.tree.TreeNode;
/**
* Parses an expression string to terms
* @see https://github.com/encog/encog-java-core/blob/master/src/test/java/org/encog/ml/prg/TestProgramClone.java
*/
public class MathExpression extends SynchronousFunctionOperator {
static EncogProgramContext context;
public MathExpression() {
super("^math");
}
final static String requireMessage = "Requires 1 string argument";
final static Term exp = Term.get("math");
@Override
protected Term function(Memory memory, Term[] x) {
//TODO this may not be thread-safe, this block may need synchronized:
if (context == null) {
context = new EncogProgramContext();
context.loadAllFunctions();
}
if (x.length!=1) {
throw new RuntimeException(requireMessage);
}
Term content = x[0];
if (content.getClass()!=Term.class) {
throw new RuntimeException(requireMessage);
}
String expstring = unescape(content.name()).toString();
if (expstring.startsWith("\""))
expstring = expstring.substring(1, expstring.length()-1);
EncogProgram p = context.createProgram(expstring);
return getTerm(p.getRootNode());
}
@Override
protected Term getRange() {
return exp;
}
public static Term getTerm(TreeNode node) {
CharSequence name =
node instanceof ProgramNode ?
("\"" + Texts.escape(((ProgramNode)node).getName()) + '\"'):
node.getClass().getSimpleName();
List<TreeNode> children = node.getChildNodes();
ExpressionValue[] data = null;
ProgramNode p = (ProgramNode)node;
data = p.getData();
if ((children == null) || (children.isEmpty())) {
if ((data == null) || (data.length == 0) || (p.isVariable())) {
if (p.isVariable()) {
long idx = data[0].toIntValue();
String varname = p.getOwner().getVariables().getVariableName((int)idx);
return Term.get(varname);
}
return Term.get(name);
}
else
return getTerms(data);
}
if ((data!=null) && (data.length > 0))
return Inheritance.make(new Product(getTerms(children), getTerms(data)), Term.get(name));
else
return Inheritance.make(getTerms(children), Term.get(name));
}
public static Term getTerms(List<TreeNode> children) {
if (children.size() == 1)
return getTerm(children.get(0));
Term[] c = new Term[children.size()];
int j = 0;
for (TreeNode t : children) {
c[j++] = getTerm(t);
}
return new Product(c);
}
public static Term getTerms(ExpressionValue[] data) {
if (data.length == 1)
return getTerm(data[0]);
Term[] c = new Term[data.length];
int j = 0;
for (ExpressionValue t : data) {
c[j++] = getTerm(t);
}
return new Product(c);
}
public static Term getTerm(ExpressionValue t) {
return Inheritance.make(
Term.get(Texts.escape(t.toStringValue())),
Term.get(t.getExpressionType().toString()));
}
}