001/* A Unit equation which is a prticular type of Unit Constraint.
002
003 Copyright (c) 2003-2014 The Regents of the University of California.
004 All rights reserved.
005 Permission is hereby granted, without written agreement and without
006 license or royalty fees, to use, copy, modify, and distribute this
007 software and its documentation for any purpose, provided that the above
008 copyright notice and the following two paragraphs appear in all copies
009 of this software.
010
011 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
012 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
013 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
014 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
015 SUCH DAMAGE.
016
017 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
018 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
019 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
020 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
021 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
022 ENHANCEMENTS, OR MODIFICATIONS.
023
024 PT_COPYRIGHT_VERSION_3
025 COPYRIGHTENDKEY
026 */
027package ptolemy.moml.unit;
028
029import java.util.Vector;
030
031import ptolemy.kernel.util.IllegalActionException;
032
033///////////////////////////////////////////////////////////////////
034//// UnitEquation
035
036/** A Unit equation is a particular type of Unit constraint, another
037 type being a Unit inequality.
038
039 @author Rowland R Johnson
040 @version $Id$
041 @since Ptolemy II 8.0
042 @Pt.ProposedRating Red (rowland)
043 @Pt.AcceptedRating Red (rowland)
044 */
045public class UnitEquation extends UnitConstraint implements UnitPresentation {
046    /** Construct a UnitEquation from the left and right hand sides.
047     * @param lhs The left hand side.
048     * @param rhs The right hand side.
049     */
050    public UnitEquation(UnitExpr lhs, UnitExpr rhs) {
051        super(lhs, "=", rhs);
052    }
053
054    ///////////////////////////////////////////////////////////////////
055    ////                         public methods                    ////
056
057    /** Return true if the equations are all satisfied.
058     * @param equations The equations.
059     * @return True if the equations are all satisfied.
060     */
061    public static boolean areSatisfied(Vector equations) {
062        for (int i = 0; i < equations.size(); i++) {
063            if (((UnitEquation) equations.elementAt(i)).isSatisfied() != true) {
064                return false;
065            }
066        }
067
068        return true;
069    }
070
071    /** Transform to the canonical form of the equation.
072     * The canonical form of an equation is
073     * <pre>
074     * Ex1, Ex2, ..., Exn = A
075     * </pre>
076     * where each Exi is a Unit term containing only one variable, and A is a
077     * Unit term containing one Unit and no variables.
078     * @return unitEquation The UnitEquation in canonical form.
079     */
080    public UnitEquation canonicalize() {
081        UnitExpr lhsUExpr = getLhs();
082        UnitExpr rhsUExpr = getRhs();
083        UnitExpr newLeftUExpr = new UnitExpr();
084        UnitExpr newRightUExpr = new UnitExpr();
085        Vector leftUTerms = lhsUExpr.getUTerms();
086
087        for (int i = 0; i < leftUTerms.size(); i++) {
088            UnitTerm uTerm = (UnitTerm) leftUTerms.elementAt(i);
089
090            if (uTerm.isUnit()) {
091                newRightUExpr.addUnitTerm(uTerm.invert());
092            } else if (uTerm.isVariable()) {
093                newLeftUExpr.addUnitTerm(uTerm);
094            }
095        }
096
097        Vector rightUTerms = rhsUExpr.getUTerms();
098
099        for (int i = 0; i < rightUTerms.size(); i++) {
100            UnitTerm uTerm = (UnitTerm) rightUTerms.elementAt(i);
101
102            if (uTerm.isUnit()) {
103                newRightUExpr.addUnitTerm(uTerm);
104            } else if (uTerm.isVariable()) {
105                newLeftUExpr.addUnitTerm(uTerm.invert());
106            }
107        }
108
109        if (newRightUExpr.getUTerms().isEmpty()) {
110            UnitTerm x = new UnitTerm();
111            x.setUnit(UnitLibrary.Identity);
112            newRightUExpr.addUnitTerm(x);
113        }
114
115        newRightUExpr = newRightUExpr.reduce();
116        return new UnitEquation(newLeftUExpr, newRightUExpr);
117    }
118
119    /** Make a copy where the left and right sides are alos copied.
120     * @return The copy.
121     */
122    public UnitEquation copy() {
123        UnitEquation uE = new UnitEquation(getLhs().copy(), getRhs().copy());
124        return uE;
125    }
126
127    /** Return true if this equation is satisfied.
128     * @return True if this equation is satisfied.
129     */
130    public boolean isSatisfied() {
131        UnitExpr lhsReduced = getLhs().reduce();
132        UnitExpr rhsReduced = getRhs().reduce();
133        Unit lhsUnit = lhsReduced.getSingleUnit();
134        Unit rhsUnit = rhsReduced.getSingleUnit();
135
136        if (lhsUnit == null || rhsUnit == null) {
137            return false;
138        }
139
140        if (lhsUnit.hasSameType(rhsUnit)) {
141            return true;
142        } else {
143            return false;
144        }
145    }
146
147    /** Visit this Unit equation (on the way to visiting the leaves)
148     * @param visitor The visitor.
149     * @return Whatever may be returned by the visitor.
150     * @exception IllegalActionException Not thrown in this base class.
151     */
152    public Object visit(EquationVisitor visitor) throws IllegalActionException {
153        return visitor._visitUnitEquation(this);
154    }
155}