package org.matheclipse.core.patternmatching;

import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.matheclipse.core.eval.EvalEngine;
import org.matheclipse.core.expression.F;
import org.matheclipse.core.interfaces.IAST;
import org.matheclipse.core.interfaces.IEvaluationEngine;
import org.matheclipse.core.interfaces.IExpr;
import org.matheclipse.core.interfaces.IPattern;
import org.matheclipse.core.interfaces.ISymbol;

import com.google.common.collect.ArrayListMultimap;

/**
 * The pattern matching rules associated with a symbol.
 */
public class UpRulesData implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 779382003637253257L;

	private transient Map fEqualUpRules;
	private transient ArrayListMultimap fSimplePatternUpRules;

	public UpRulesData() {
		this.fEqualUpRules = null;
		this.fSimplePatternUpRules = null;
	}

	public void clear() {
		fEqualUpRules = null;
		fSimplePatternUpRules = null;
	}

	public IExpr evalUpRule(final IEvaluationEngine ee, final IExpr expression) {
		PatternMatcherEquals res;
		if (fEqualUpRules != null) {
			res = fEqualUpRules.get(expression);
			if (res != null) {
				return res.getRHS();
			}
		}

		try {
			IExpr result;
			IPatternMatcher pmEvaluator;
			if ((fSimplePatternUpRules != null) && (expression.isAST())) {
				final Integer hash = Integer.valueOf(((IAST) expression).patternHashCode());
				final List list = fSimplePatternUpRules.get(hash);
				if (list != null) {
					for (int i = 0; i < list.size(); i++) {
						pmEvaluator = (IPatternMatcher) list.get(i).clone();
						result = pmEvaluator.eval(expression);
						if (result != null) {
							return result;
						}
					}
				}
			}

		} catch (CloneNotSupportedException cnse) {
			cnse.printStackTrace();
		}
		return null;
	}

	public IPatternMatcher putUpRule(ISymbol setSymbol, final boolean equalRule, final IAST leftHandSide,
			final IExpr rightHandSide, final int priority) {
		if (equalRule) {
			fEqualUpRules = getEqualUpRules();
			PatternMatcherEquals pmEquals = new PatternMatcherEquals(setSymbol, leftHandSide, rightHandSide);
			fEqualUpRules.put(leftHandSide, pmEquals);
			return pmEquals;
		}

		final PatternMatcherAndEvaluator pmEvaluator = new PatternMatcherAndEvaluator(setSymbol, leftHandSide, rightHandSide);

		if (pmEvaluator.isRuleWithoutPatterns()) {
			fEqualUpRules = getEqualUpRules();
			PatternMatcherEquals pmEquals = new PatternMatcherEquals(setSymbol, leftHandSide, rightHandSide);
			fEqualUpRules.put(leftHandSide, pmEquals);
			return pmEquals;
		}

		fSimplePatternUpRules = getSimplePatternUpRules();
		return addSimplePatternUpRule(leftHandSide, pmEvaluator);

	}

	/**
	 * Create a pattern hash value for the left-hand-side expression and insert
	 * the left-hand-side as a simple pattern rule to the
	 * fSimplePatternRules.
	 * 
	 * @param leftHandSide
	 * @param pmEvaluator
	 * @return
	 */
	private PatternMatcher addSimplePatternUpRule(final IExpr leftHandSide, final PatternMatcher pmEvaluator) {
		final Integer hash = Integer.valueOf(((IAST) leftHandSide).patternHashCode());
		if (F.isSystemInitialized && fSimplePatternUpRules.containsEntry(hash, pmEvaluator)) {
			fSimplePatternUpRules.remove(hash, pmEvaluator);
		}
		fSimplePatternUpRules.put(hash, pmEvaluator);
		return pmEvaluator;
	}

	private boolean isComplicatedPatternRule(final IExpr lhsExpr) {
		if (lhsExpr.isAST()) {
			final IAST lhsAST = ((IAST) lhsExpr);
			if (lhsAST.size() > 1) {
				final int attr = lhsAST.topHead().getAttributes();
				if ((ISymbol.ORDERLESS & attr) == ISymbol.ORDERLESS) {
					return true;
				}
				if (lhsAST.get(1).isAST()) {
					IAST arg1 = (IAST) lhsAST.get(1);
					if (arg1.isCondition()) {
						return true;
					}
					// the left hand side is associated with the first argument
					// see if the first argument is complicated
					for (int i = 2; i < arg1.size(); i++) {
						if (arg1.get(i).isPattern() && ((IPattern) arg1.get(i)).isDefault()) {
							return true;
						}
					}
				} else if (lhsAST.get(1).isPattern()) {
					return true;
				} else if (lhsAST.get(1).isPatternSequence()) {
					return true;
				}
				for (int i = 2; i < lhsAST.size(); i++) {
					if (lhsAST.get(i).isPattern() && ((IPattern) lhsAST.get(i)).isDefault()) {
						return true;
					}
				}
			}
		} else if (lhsExpr.isPattern()) {
			return true;
		} else if (lhsExpr.isPatternSequence()) {
			return true;
		}
		return false;
	}

	/**
	 * @return Returns the equalRules.
	 */
	public Map getEqualUpRules() {
		if (fEqualUpRules == null) {
			fEqualUpRules = new HashMap();
		}
		return fEqualUpRules;
	}

	private ArrayListMultimap getSimplePatternUpRules() {
		if (fSimplePatternUpRules == null) {
			fSimplePatternUpRules = ArrayListMultimap.create();
		}
		return fSimplePatternUpRules;
	}

	public List definition() {
		ArrayList definitionList = new ArrayList();
		Iterator iter;
		IExpr key;
		PatternMatcherEquals pme;
		IExpr condition;
		ISymbol setSymbol;
		IAST ast;
		PatternMatcherAndEvaluator pmEvaluator;
		if (fEqualUpRules != null && fEqualUpRules.size() > 0) {
			iter = fEqualUpRules.keySet().iterator();
			while (iter.hasNext()) {
				key = iter.next();
				pme = fEqualUpRules.get(key);
				setSymbol = pme.getSetSymbol();
				ast = F.ast(setSymbol);
				ast.add(key);
				ast.add(pme.getRHS());
				definitionList.add(ast);
			}
		}
		if (fSimplePatternUpRules != null && fSimplePatternUpRules.size() > 0) {
			Iterator listIter = fSimplePatternUpRules.values().iterator();
			IPatternMatcher elem;
			while (listIter.hasNext()) {
				elem = listIter.next();
				if (elem instanceof PatternMatcherAndEvaluator) {
					pmEvaluator = (PatternMatcherAndEvaluator) elem;
					setSymbol = pmEvaluator.getSetSymbol();

					ast = F.ast(setSymbol);
					ast.add(pmEvaluator.getLHS());
					condition = pmEvaluator.getCondition();
					if (condition != null) {
						ast.add(F.Condition(pmEvaluator.getRHS(), condition));
					} else {
						ast.add(pmEvaluator.getRHS());
					}
					definitionList.add(ast);
				}
				// if (elem instanceof PatternMatcherAndInvoker) {
				// don't show internal methods associated with a pattern
				// }
			}
		}

		return definitionList;
	}

	public void readSymbol(java.io.ObjectInputStream stream) throws IOException {

		String astString;
		IExpr key;
		IExpr value;
		EvalEngine engine = EvalEngine.get();
		ISymbol setSymbol;
		int len = stream.read();
		if (len > 0) {
			// fEqualRules = new HashMap>();
			// for (int i = 0; i < len; i++) {
			// astString = stream.readUTF();
			// setSymbol = F.$s(astString);
			//
			// astString = stream.readUTF();
			// key = engine.parse(astString);
			// astString = stream.readUTF();
			// value = engine.parse(astString);
			// fEqualRules.put(key, new Pair(setSymbol, value));
			// }
			fEqualUpRules = new HashMap();
			for (int i = 0; i < len; i++) {
				astString = stream.readUTF();
				setSymbol = F.$s(astString);

				astString = stream.readUTF();
				key = engine.parse(astString);
				astString = stream.readUTF();
				value = engine.parse(astString);
				fEqualUpRules.put(key, new PatternMatcherEquals(setSymbol, key, value));
			}
		}

		len = stream.read();
		IExpr lhs;
		IExpr rhs;
		IExpr condition;
		int listLength;
		int condLength;
		PatternMatcherAndEvaluator pmEvaluator;
		if (len > 0) {
			fSimplePatternUpRules = ArrayListMultimap.create();
			for (int i = 0; i < len; i++) {
				astString = stream.readUTF();
				setSymbol = F.$s(astString);

				astString = stream.readUTF();
				lhs = engine.parse(astString);
				astString = stream.readUTF();
				rhs = engine.parse(astString);
				pmEvaluator = new PatternMatcherAndEvaluator(setSymbol, lhs, rhs);

				condLength = stream.read();
				if (condLength == 0) {
					condition = null;
				} else {
					astString = stream.readUTF();
					condition = engine.parse(astString);
					pmEvaluator.setCondition(condition);
				}
				addSimplePatternUpRule(lhs, pmEvaluator);
			}

		}
	}

	public void writeSymbol(java.io.ObjectOutputStream stream) throws java.io.IOException {
		Iterator iter;
		IExpr key;
		IExpr condition;

		PatternMatcherEquals pme;
		ISymbol setSymbol;
		PatternMatcherAndEvaluator pmEvaluator;
		if (fEqualUpRules == null || fEqualUpRules.size() == 0) {
			stream.write(0);
		} else {
			stream.write(fEqualUpRules.size());
			iter = fEqualUpRules.keySet().iterator();
			while (iter.hasNext()) {
				key = iter.next();
				pme = fEqualUpRules.get(key);
				stream.writeUTF(pme.getLHS().toString());
				stream.writeUTF(key.fullFormString());
				stream.writeUTF(pme.getRHS().fullFormString());
			}
		}

		if (fSimplePatternUpRules == null || fSimplePatternUpRules.size() == 0) {
			stream.write(0);
		} else {
			stream.write(fSimplePatternUpRules.size());
			Iterator listIter = fSimplePatternUpRules.values().iterator();
			IPatternMatcher elem;
			while (listIter.hasNext()) {
				elem = listIter.next();
				pmEvaluator = (PatternMatcherAndEvaluator) elem;
				setSymbol = pmEvaluator.getSetSymbol();
				stream.writeUTF(setSymbol.toString());
				stream.writeUTF(pmEvaluator.getLHS().fullFormString());
				stream.writeUTF(pmEvaluator.getRHS().fullFormString());
				condition = pmEvaluator.getCondition();
				if (condition == null) {
					stream.write(0);
				} else {
					stream.write(1);
					stream.writeUTF(condition.fullFormString());
				}
			}
		}
	}
}
 

Ads help maintain this website.