package org.matheclipse.core.patternmatching;
import java.util.List;
import org.matheclipse.core.convert.AST2Expr;
import org.matheclipse.core.expression.F;
import org.matheclipse.core.interfaces.IAST;
import org.matheclipse.core.interfaces.IExpr;
import org.matheclipse.core.visit.HashValueVisitor;
import org.matheclipse.parser.client.Parser;
import org.matheclipse.parser.client.SyntaxError;
import org.matheclipse.parser.client.ast.ASTNode;
import com.google.common.collect.ArrayListMultimap;
/**
* Match two arguments of an Orderless AST into a new resulting expression.
*
* @see HashedPatternRules
*/
public class HashedOrderlessMatcher {
ArrayListMultimap hashRuleMap;
private final boolean fDefaultHashCode;
public HashedOrderlessMatcher(boolean defaultHashCode) {
this.fDefaultHashCode = defaultHashCode;
this.hashRuleMap = ArrayListMultimap.create();
}
/**
* Define the rule for the Orderless operator OP. OP[lhs1Str, rhsStr, ....] := OP[rhsStr, ...]
*
* @param lhs1Str
* @param lhs2Str
* @param rhsStr
* @throws SyntaxError
*/
public void setUpHashRule(final String lhs1Str, final String lhs2Str, final String rhsStr) throws SyntaxError {
setUpHashRule(lhs1Str, lhs2Str, rhsStr, null);
}
public void setUpHashRule(final String lhs1Str, final String lhs2Str, final String rhsStr, final String conditionStr)
throws SyntaxError {
final Parser parser = new Parser();
ASTNode parsedAST = parser.parse(lhs1Str);
final IExpr lhs1 = AST2Expr.CONST.convert(parsedAST);
parsedAST = parser.parse(lhs2Str);
final IExpr lhs2 = AST2Expr.CONST.convert(parsedAST);
parsedAST = parser.parse(rhsStr);
final IExpr rhs = AST2Expr.CONST.convert(parsedAST);
IExpr condition = null;
if (conditionStr != null) {
parsedAST = parser.parse(conditionStr);
condition = AST2Expr.CONST.convert(parsedAST);
}
setUpHashRule(lhs1, lhs2, rhs, condition);
}
/**
* Define the rule for the Orderless operator OP.
* OP[lhs1Str, rhsStr, ....] := OP[rhsStr, ...] /; condition
*
* @param lhs1
* @param lhs2
* @param rhs
*/
public void setUpHashRule(final IExpr lhs1, final IExpr lhs2, final IExpr rhs) {
setUpHashRule(lhs1, lhs2, rhs, null);
}
/**
* Define the rule for the Orderless operator OP.
* OP[lhs1Str, rhsStr, ....] := OP[rhsStr, ...] /; condition
*
* @param lhs1
* @param lhs2
* @param rhs
* @param condition
*/
public void setUpHashRule(final IExpr lhs1, final IExpr lhs2, final IExpr rhs, final IExpr condition) {
HashedPatternRules hashRule = new HashedPatternRules(lhs1, lhs2, rhs, condition, fDefaultHashCode);
hashRuleMap.put(hashRule.getHash1(), hashRule);
}
/**
* Evaluate an Orderless AST with the defined HashedPatternRules.
*
* @param orderlessAST
* @return
* @see HashedPatternRules
*/
public IAST evaluate(final IAST orderlessAST) {
int[] hashValues = new int[(orderlessAST.size() - 1)];
if (fDefaultHashCode) {
for (int i = 0; i < hashValues.length; i++) {
hashValues[i] = orderlessAST.get(i + 1).head().hashCode();
}
} else {
HashValueVisitor v = new HashValueVisitor();
for (int i = 0; i < hashValues.length; i++) {
hashValues[i] = orderlessAST.get(i + 1).accept(v);
v.setUp();
}
}
return evaluateHashedValues(orderlessAST, hashValues);
}
private IAST evaluateHashedValues(final IAST orderlessAST, int[] hashValues) {
boolean evaled = false;
IAST result = null;
IExpr temp;
for (int i = 0; i < hashValues.length; i++) {
if (hashValues[i] == 0) {
// already used entry
continue;
}
final List hashRuleList = hashRuleMap.get(hashValues[i]);
if (hashRuleList != null) {
evaled: for (HashedPatternRules hashRule : hashRuleList) {
for (int j = 0; j < hashValues.length; j++) {
if (!hashRule.isPattern2()) {
if (hashValues[j] != hashRule.getHash2() || j == i) {
// hash code of both entries aren't matching
continue;
}
}
DownRulesData rulesData = hashRule.getRulesData();
if ((temp = rulesData.evalDownRule(F.List(orderlessAST.get(i + 1), orderlessAST.get(j + 1)))) != null) {
hashValues[i] = 0;
hashValues[j] = 0;
if (!evaled) {
result = orderlessAST.copyHead();
evaled = true;
}
result.add(temp);
break evaled;
}
}
}
}
}
if (evaled) {
// append rest of unevaluated arguments
for (int i = 0; i < hashValues.length; i++) {
if (hashValues[i] != 0) {
result.add(orderlessAST.get(i + 1));
}
}
}
return result;
}
}
Ads help maintain this website.