/* * Below is the copyright agreement for the Ptolemy II system. * * Copyright (c) 2009 The Regents of the University of California. All rights * reserved. * * Permission is hereby granted, without written agreement and without license * or royalty fees, to use, copy, modify, and distribute this software and its * documentation for any purpose, provided that the above copyright notice and * the following two paragraphs appear in all copies of this software. * * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN * "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE * MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. */ package ptolemy.domains.properties.kernel; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import ptolemy.data.properties.lattice.LatticeProperty; import ptolemy.data.properties.lattice.PropertyLattice; import ptolemy.domains.modal.kernel.FSMActor; import ptolemy.graph.GraphStateException; import ptolemy.kernel.CompositeEntity; import ptolemy.kernel.Port; import ptolemy.kernel.util.IllegalActionException; import ptolemy.kernel.util.NameDuplicationException; import ptolemy.kernel.util.Workspace; import ptolemy.util.MessageHandler; /** * A PropertyLatticeComposite contains a set of lattice elements and their * connections. * * @author Man-Kit Leung * @version $Id$ * @since Ptolemy II 7.1 * @Pt.ProposedRating Red (mankit) * @Pt.AcceptedRating Red (mankit) */ public class PropertyLatticeComposite extends FSMActor { /** * Create an PropertyLatticeComposite in the specified container with the * specified name. The name must be unique within the container or an * exception is thrown. The container argument must not be null, or a * NullPointerException will be thrown. * @param container The specified container. * @param name The specified name. * @exception IllegalActionException If the entity cannot be contained by * the proposed container. * @exception NameDuplicationException If the name coincides with an entity * already in the container. */ public PropertyLatticeComposite(CompositeEntity container, String name) throws IllegalActionException, NameDuplicationException { super(container, name); } /** * Construct an PropertyLatticeComposite in the specified workspace with an * empty string as its name. Add the actor to the workspace directory. * @param workspace The workspace that will list the actor. */ public PropertyLatticeComposite(Workspace workspace) { super(workspace); } /////////////////////////////////////////////////////////////////// //// public methods //// /** * Return true if the contained elements form a lattice; false, otherwise. * @return True if the contained elements form a lattice, otherwise false. */ public boolean isLattice() { List<LatticeElement> elements = deepEntityList(); _clearHighlightColor(elements); PropertyLattice lattice = new Lattice(elements); // 06/03/2009 Charles Shelton - Bug fixes for the isLattice() function: // - Catch the exception from the directed acyclic graph _validate() method that checks for a cycle in the graph // - LatticeProperty class is derived from the Property class and not the NamedObj class and cannot be cast to NamedObj // so replace all getName() calls with toString() // - The elements list contains LatticeElement objects, not LatticeProperty objects, so the leastUpeperBound() method does not work. // use the list of LatticeProperty objects from the newly created Lattice object instead. // - Added additional debug messages to provide both positive and negative feedback about the lattice. try { if (lattice.top() == null) { _debug("This is not a lattice."); MessageHandler.error("Cannot find an unique top element."); return false; } else { LatticeProperty top = (LatticeProperty) lattice.top(); _debug("Top is: " + top.toString()); } } catch (GraphStateException e) { _debug("This is not a lattice."); MessageHandler .error("Proposed lattice has a cycle and is not a true lattice."); return false; } if (lattice.bottom() == null) { _debug("This is not a lattice."); MessageHandler.error("Cannot find an unique bottom element."); return false; } else { LatticeProperty bottom = (LatticeProperty) lattice.bottom(); _debug("Bottom is: " + bottom.toString()); } List<LatticeProperty> latticeProperties = ((Lattice) lattice) .getLatticeProperties(); // This is the same check done in ptolemy.graph.DirectedAcyclicGraph. for (int i = 0; i < latticeProperties.size() - 1; i++) { for (int j = i + 1; j < latticeProperties.size(); j++) { LatticeProperty lub = (LatticeProperty) lattice .leastUpperBound(latticeProperties.get(i), latticeProperties.get(j)); if (lub == null) { // FIXME: add highlight color? // The offending nodes. _debug("This is not a lattice."); MessageHandler .error("\"" + elements.get(i).getName() + "\" and \"" + elements.get(j).getName() + "\"" + " does not have an unique least upper bound (LUB)."); return false; } else { _debug("LUB(" + elements.get(i).getName() + ", " + elements.get(j).getName() + "): " + lub.toString()); } } } _debug("This is a correctly formed lattice."); return true; } /////////////////////////////////////////////////////////////////// //// public inner class //// /** * A PropertyLattice that is constructed from a Ptolemy model. */ public static class Lattice extends PropertyLattice { /** * Construct a lattice from a specified list of lattice elements. This * connects the lattice elements according to the port connections * between the lattice elements. * @param elements The specified list of lattice elements. */ public Lattice(List<LatticeElement> elements) { _properties = new ArrayList(); HashMap map = new HashMap(); // First add the property nodes to the lattice. for (LatticeElement element : elements) { LatticeProperty property = new LatticeProperty(this, element .getName()); property.setColor(element.solutionColor.getExpression()); _properties.add(property); addNodeWeight(property); map.put(element, property); } // Create edges to connect the nodes. for (LatticeElement element : elements) { // for each outgoing edge. for (Port port : (List<Port>) element.outgoingPort .connectedPortList()) { addEdge(map.get(element), map.get(port.getContainer())); } } } /** * Return a LatticeProperty that is labeled with the specified name. * @param name The specified name. * @return A LatticeProperty. * @throws IllegalActionException If no element with the specified name * is found. */ public LatticeProperty getElement(String name) throws IllegalActionException { for (LatticeProperty property : _properties) { if (name.equalsIgnoreCase(property.toString())) { return property; } } throw new IllegalActionException("No such element named: \"" + name + "\" in the lattice."); } /** * Return the properties in the lattice. * @return The list of LatticeProperty in the lattice. */ // 06/03/2009 Charles Shelton - Public method to access the list // of LatticeProperty objects. public List<LatticeProperty> getLatticeProperties() { return _properties; } /////////////////////////////////////////////////////////////////// //// inner private variables //// private final List<LatticeProperty> _properties; } /////////////////////////////////////////////////////////////////// //// private methods //// private void _clearHighlightColor(List<LatticeElement> elements) { // TODO Auto-generated method stub } }