/* * Copyright 2006, United States Government as represented by the Administrator * for the National Aeronautics and Space Administration. No copyright is * claimed in the United States under Title 17, U.S. Code. All Other Rights * Reserved. */ package gov.nasa.ial.mde.solver.symbolic; import gov.nasa.ial.mde.util.SortedKeyStrings; import java.util.Enumeration; import java.util.Hashtable; /** * The polynomial terms. * * @author Dr. Robert Shelton * @version 1.0 * @since 1.0 */ public class PolyTerm { // see description of `termHash' in Polynomial.java private String signature = Polynomial.CONSTANT; private Hashtable<String, Integer> exponents; // keys are variables, values are exponents private Expression coefficient; private String[] variables = new String[0]; private int degree; /** * Default constructor. */ public PolyTerm() { exponents = new Hashtable<String,Integer>(); degree = -1; // flag value that triggers first-time computation of the degree } // end PolyTerm /** * Returns the coefficient as an expression. * * @return the coefficient as an expression. */ public Expression getCoefficient() { return coefficient; } // end getCoefficient /** * Returns the variables. * * @return the variables. */ public String[] getVariables() { return variables; } // end getVariables /** * Returns the degree of the specified variable. * * @param var the variable. * @return the degree. */ public int getDegreeOfVariable(String var) { Integer Deg = (Integer)exponents.get(var); if (Deg == null) return 0; return Deg.intValue(); } // end getDegreeOfVariable /** * Returns the degree. * * @return the degree. */ public int getDegree() { if (degree < 0) { int i, n = variables.length; for (i = degree = 0; i < n; i++) degree += ((Integer)exponents.get(variables[i])).intValue(); } // end if return degree; } // end getDegree /** * Returns the signature. * * @return the signature. */ public String getSignature() { return signature; } // end getSignature /** * Sets the coefficient. * * @param c the coefficient. */ public void setCoefficient(Expression c) { coefficient = c; } // end setCoefficient /** * Set the exponent for the specified variable. * * @param v the variable. * @param e the exponent. */ public void setExponent(Expression v, int e) { exponents.put(v.toString(), new Integer(e)); doSignature(); } // end setExponent /** * Returns the sum of this PolyTerm with the specified other PolyTerm. * * @param other the other polyTerm. * @return the sum of this PolyTerm with the specified other PolyTerm. */ public PolyTerm sum(PolyTerm other) { PolyTerm r = new PolyTerm(); r.exponents = exponents; r.coefficient = coefficient.sum(other.coefficient); if (r.coefficient.valueString != null) r.coefficient = new Expression(r.coefficient.valueString); r.doSignature(); return r; } // end sum /** * Returns the negative of this PolyTerm. * * @return the negative of this PolyTerm. */ public PolyTerm makeNegative() { PolyTerm t = new PolyTerm(); t.exponents = exponents; t.signature = signature; t.coefficient = Expression.negate(coefficient); if (t.coefficient.valueString != null) t.coefficient = new Expression(t.coefficient.valueString); t.doSignature(); return t; } // end makeNegatigve /** * Negates this PolyTerm. */ public void negate() { coefficient = Expression.negate(coefficient); if (coefficient.valueString != null) coefficient = new Expression(coefficient.valueString); } // end negate /** * Returns the product of this PolyTerm and the other PolyTerm. * * @param other the other PolyTerm. * @return the product of this PolyTerm and the other PolyTerm. */ public PolyTerm product(PolyTerm other) { PolyTerm r = new PolyTerm(); Enumeration<String> k = exponents.keys(); r.coefficient = coefficient.product(other.coefficient); if (r.coefficient.valueString != null) r.coefficient = new Expression(r.coefficient.valueString); while (k.hasMoreElements()) { String s = (String)k.nextElement(); Integer I = (Integer)exponents.get(s), J = (Integer)other.exponents.get(s); if (J != null) r.exponents.put(s, new Integer(I.intValue() + J.intValue())); else r.exponents.put(s, I); } // end while for (k = other.exponents.keys(); k.hasMoreElements();) { String s = (String)k.nextElement(); if (exponents.get(s) != null) continue; // skip since common vars are already done r.exponents.put(s, other.exponents.get(s)); } // end for r.doSignature(); return r; } // end product /** * Returns an expression for the PolyTerm. * * @return the expression for the PolyTerm. */ public Expression makeExpression() { if (coefficient == null) return null; int i, n = exponents.size(); if (n == 0) return coefficient; ParseNode p = new ParseNode(n + 1, Action.PRODUCT); p.children[0] = coefficient.root; for (i = 0; i < n; i++) { int d = getDegreeOfVariable(variables[i]); if (d > 1) { p.children[i + 1] = new ParseNode(2, Action.POWER); p.children[i + 1].children[0] = new ParseNode(variables[i]); p.children[i + 1].children[1] = new ParseNode("" + d); } // end if else p.children[i + 1] = new ParseNode(variables[i]); } // end for i return new Expression(p); } // end makeExpression /** * Returns a derivative given the specified variable. * * @param variable the variable in the PolyTerm. * @return the derivative. */ public PolyTerm makeDerivative(String variable) { PolyTerm p = new PolyTerm(); Integer N = (Integer)exponents.get(variable); int n; if (N == null) return p; p.coefficient = coefficient.product(new Expression(N.toString())); if (p.coefficient.valueString != null) p.coefficient = new Expression(p.coefficient.valueString); for (Enumeration<String> k = exponents.keys(); k.hasMoreElements();) { String v = k.nextElement(); if (v.equals(variable)) { if ((n = N.intValue()) > 1) p.exponents.put(v, new Integer(n - 1)); } // end if else p.exponents.put(v, exponents.get(v)); } // end for k p.doSignature(); return p; } // end differentiate /** * Returns the signature given the exponents. * * @param e the exponents. * @return the signature. */ public static String[] makeSignature(Hashtable<String, Integer> e) { if (e.isEmpty()) return new String[0]; StringBuffer b = new StringBuffer(); SortedKeyStrings s = new SortedKeyStrings(e); int i, n = s.theKeys.length; b.append(s.theKeys[0] + "^" + ((Integer)e.get(s.theKeys[0])).toString()); for (i = 1; i < n; i++) b.append(":" + s.theKeys[i] + "^" + ((Integer)e.get(s.theKeys[i])).toString()); String[] r = new String[n + 1]; for (i = 0; i < n; i++) r[i] = s.theKeys[i]; r[n] = b.toString(); return r; } // end makeSignature private void doSignature() { String[] r = makeSignature(exponents); int i, n = r.length - 1; if (n < 0) return; variables = new String[n]; for (i = 0; i < n; i++) variables[i] = r[i]; signature = r[n]; } // end doSignature // public void autoTest() { // if (variables.length != exponents.size()) { // System.err.println("Oops!"); // System.exit(1); // } // end if // } // end autoTest } // end class PolyTerm