001/* An actor that outputs the minimum value that it has received since the start
002of execution.
003
004 Copyright (c) 2008-2014 The Regents of the University of California.
005 All rights reserved.
006 Permission is hereby granted, without written agreement and without
007 license or royalty fees, to use, copy, modify, and distribute this
008 software and its documentation for any purpose, provided that the above
009 copyright notice and the following two paragraphs appear in all copies
010 of this software.
011
012 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
013 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
014 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
015 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
016 SUCH DAMAGE.
017
018 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
019 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
020 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
021 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
022 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
023 ENHANCEMENTS, OR MODIFICATIONS.
024
025 PT_COPYRIGHT_VERSION_2
026 COPYRIGHTENDKEY
027
028 */
029package ptolemy.actor.lib;
030
031import java.util.HashSet;
032import java.util.Set;
033
034import ptolemy.data.ScalarToken;
035import ptolemy.data.type.BaseType;
036import ptolemy.data.type.TypeConstant;
037import ptolemy.graph.Inequality;
038import ptolemy.kernel.CompositeEntity;
039import ptolemy.kernel.util.IllegalActionException;
040import ptolemy.kernel.util.NameDuplicationException;
041import ptolemy.kernel.util.Workspace;
042
043/**
044 Output the minimum value seen since the start of execution of the model.
045 On each firing, this actor consumes exactly one scalar token at its input port.
046 The value of the token is compared to the minimum value maintained since the
047 start of the execution. The lesser of the two is output to the output port in
048 the same firing, and the minimum value is set with that greater value in
049 postfire().
050
051 @author Thomas Huining Feng
052 @version $Id$
053 @since Ptolemy II 10.0
054 @Pt.ProposedRating Yellow (tfeng)
055 @Pt.AcceptedRating Red (tfeng)
056 */
057public class RunningMinimum extends Transformer {
058
059    /** Construct an actor with the specified container and name.
060     *
061     *  @param container The composite actor to contain this one.
062     *  @param name The name of this actor.
063     *  @exception IllegalActionException If the entity cannot be contained
064     *   by the proposed container.
065     *  @exception NameDuplicationException If the container already has an
066     *   actor with this name.
067     */
068    public RunningMinimum(CompositeEntity container, String name)
069            throws NameDuplicationException, IllegalActionException {
070        super(container, name);
071    }
072
073    ///////////////////////////////////////////////////////////////////
074    ////                         public methods                    ////
075
076    /** Clone this actor into the specified workspace. The new actor is
077     *  <i>not</i> added to the directory of that workspace (you must do this
078     *  yourself if you want it there).
079     *  The result is a new actor with the same ports as the original, but
080     *  no connections and no container.  A container must be set before
081     *  much can be done with this actor.
082     *
083     *  @param workspace The workspace for the cloned object.
084     *  @exception CloneNotSupportedException If cloned ports cannot have
085     *   as their container the cloned entity (this should not occur), or
086     *   if one of the attributes cannot be cloned.
087     *  @return A new ComponentEntity.
088     */
089    @Override
090    public Object clone(Workspace workspace) throws CloneNotSupportedException {
091        RunningMinimum newObject = (RunningMinimum) super.clone(workspace);
092        return newObject;
093    }
094
095    /** Consume a token at the input port, and produce the greater of that value
096     *  and the maintained minimum value to the output port.
097     *
098     *  @exception IllegalActionException If getting token from input or
099     *  sending token to output throws it.
100     */
101    @Override
102    public void fire() throws IllegalActionException {
103        super.fire();
104
105        _value = (ScalarToken) input.get(0);
106        if (_minimum == null || _value.isLessThan(_minimum).booleanValue()) {
107            output.broadcast(_value);
108        } else {
109            output.broadcast(_minimum);
110        }
111    }
112
113    /** Initialize the maintained minimum value to be null so it will be set
114     *  with the first input at the input port.
115     *
116     *  @exception IllegalActionException If the initialize() method of the
117     *  superclass throws it.
118     */
119    @Override
120    public void initialize() throws IllegalActionException {
121        super.initialize();
122
123        _minimum = null;
124    }
125
126    /** Commit the minimum value observed since the start of execution to the
127     *  minimum field to be compared with later inputs.
128     *
129     *  @exception IllegalActionException If the postfire() method of the
130     *  superclass throws it.
131     */
132    @Override
133    public boolean postfire() throws IllegalActionException {
134        boolean result = super.postfire();
135
136        if (_minimum == null || _value.isLessThan(_minimum).booleanValue()) {
137            _minimum = _value;
138        }
139
140        return result;
141    }
142
143    /** Return true if the prefire() method of the superclass returns true, and
144     *  there is at least one token at the input port.
145     *
146     *  @exception IllegalActionException If the prefire() method of the
147     *  superclass throws it.
148     */
149    @Override
150    public boolean prefire() throws IllegalActionException {
151        return super.prefire() && input.hasToken(0);
152    }
153
154    ///////////////////////////////////////////////////////////////////
155    ////                         protected methods                 ////
156
157    /** Eliminate default constraints.
158     *  @return null
159     */
160    @Override
161    protected Set<Inequality> _defaultTypeConstraints() {
162        return null;
163    }
164
165    /** Set input &le; output, input &le; Scalar. If backward type inference is
166     *  enabled and input has no declared type, also set input &ge;output.
167     *  @return A set of inequality constraints.
168     */
169    @Override
170    protected Set<Inequality> _customTypeConstraints() {
171        Set<Inequality> result = new HashSet<Inequality>();
172        /* input <= output */
173        result.add(new Inequality(input.getTypeTerm(), output.getTypeTerm()));
174        /* input <= Scalar. */
175        result.add(new Inequality(input.getTypeTerm(),
176                new TypeConstant(BaseType.SCALAR)));
177        /* input >= output if backward type inference is enabled */
178        if (isBackwardTypeInferenceEnabled()
179                && input.getTypeTerm().isSettable()) {
180            result.add(
181                    new Inequality(output.getTypeTerm(), input.getTypeTerm()));
182        }
183        return result;
184    }
185
186    ///////////////////////////////////////////////////////////////////
187    ////                         private variables                 ////
188
189    // The minimum value observed so far.
190    private ScalarToken _minimum;
191
192    // The value observed in the current firing.
193    private ScalarToken _value;
194}