001/* Huffman Coder. 002 003 Copyright (c) 2004-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_2 025 COPYRIGHTENDKEY 026 027 */ 028package ptolemy.actor.lib.comm; 029 030import ptolemy.data.ArrayToken; 031import ptolemy.data.BooleanToken; 032import ptolemy.data.Token; 033import ptolemy.data.type.ArrayType; 034import ptolemy.data.type.BaseType; 035import ptolemy.kernel.CompositeEntity; 036import ptolemy.kernel.util.IllegalActionException; 037import ptolemy.kernel.util.InternalErrorException; 038import ptolemy.kernel.util.NameDuplicationException; 039import ptolemy.kernel.util.Workspace; 040 041/////////////////////////////////////////////////////////////////// 042//// HuffmanCoder 043 044/** 045 Given a probability distribution and alphabet, encode the input using 046 Huffman code and send the result in booleans to the output port. 047 Its base class HuffmanBasic generates the code book. 048 The HuffmanCoder actor simply encode the input into the corresponding 049 booleans in the code book. 050 @see HuffmanBasic 051 052 @author Ye Zhou 053 @version $Id$ 054 @since Ptolemy II 4.1 055 @Pt.ProposedRating Red (zhouye) 056 @Pt.AcceptedRating Red (cxh) 057 */ 058public class HuffmanCoder extends HuffmanBasic { 059 /** Construct an actor with the given container and name. 060 * The output and trigger ports are also constructed. 061 * @param container The container. 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 HuffmanCoder(CompositeEntity container, String name) 069 throws NameDuplicationException, IllegalActionException { 070 super(container, name); 071 072 // Declare type constraints. 073 alphabet.setTypeAtLeast(ArrayType.arrayOf(input)); 074 output.setTypeEquals(BaseType.BOOLEAN); 075 } 076 077 /////////////////////////////////////////////////////////////////// 078 //// public methods //// 079 080 /** Clone the actor into the specified workspace. This calls the 081 * base class and then creates new ports and parameters. 082 * @param workspace The workspace for the new object. 083 * @return A new actor. 084 * @exception CloneNotSupportedException If a derived class contains 085 * an attribute that cannot be cloned. 086 */ 087 @Override 088 public Object clone(Workspace workspace) throws CloneNotSupportedException { 089 HuffmanCoder newObject = (HuffmanCoder) super.clone(workspace); 090 try { 091 newObject.alphabet 092 .setTypeAtLeast(ArrayType.arrayOf(newObject.input)); 093 } catch (IllegalActionException e) { 094 // Should have been caught before. 095 throw new InternalErrorException(e); 096 } 097 return newObject; 098 } 099 100 /** Generate the Huffman codebook for the given <i>pmf</i>, and 101 * encode the input into booleans and send them to the output port. 102 */ 103 @Override 104 public void fire() throws IllegalActionException { 105 super.fire(); 106 107 ArrayToken alphabetArrayToken = (ArrayToken) alphabet.getToken(); 108 Token[] alphabetTokens = new Token[_pmf.length]; 109 110 for (int i = 0; i < _pmf.length; i++) { 111 alphabetTokens[i] = alphabetArrayToken.getElement(i); 112 } 113 114 // Get the input token. Ready for output. 115 Token inputToken = input.get(0); 116 117 // Find the token in the alphabet; 118 //boolean validInput = false; 119 120 for (int i = 0; i < _pmf.length; i++) { 121 if (inputToken.equals(alphabetTokens[i])) { 122 //validInput = true; 123 _sendBooleans(_codeBook[i]); 124 break; 125 } 126 } 127 128 // FIXME: If the input is not found in the alphabet, 129 // which means it's probability of occurrence is zero, 130 // we might want to ignore it (or give a warning message.) 131 //if (!validInput) { 132 // throw new IllegalActionException(this, 133 // "Input is not matched to the alphabet"); 134 //} 135 } 136 137 /////////////////////////////////////////////////////////////////// 138 //// private methods //// 139 140 /** Given a codeword, which should be a string of '0' and '1', 141 * converted it to a sequence of booleans and send them to the 142 * output port. 143 * @param codeword The string of codeword. 144 * @exception IllegalActionException If the output receiver throws it. 145 */ 146 private void _sendBooleans(String codeword) throws IllegalActionException { 147 for (int i = 0; i < codeword.length(); i++) { 148 if (codeword.charAt(i) == '1') { 149 output.send(0, new BooleanToken(true)); 150 } else { 151 output.send(0, new BooleanToken(false)); 152 } 153 } 154 } 155}