changeset 2544:0064fb925500 octave-forge

Adding shannon fano codes on lines of Huffman code, and removing older version of shannonfano_code inline with expectations of the other-lead...
author gnumuthu
date Mon, 02 Oct 2006 06:29:09 +0000
parents 85d419c88555
children d7f4b18f9338
files main/comm/inst/huffmandict.m main/comm/inst/shannonfanodeco.m main/comm/inst/shannonfanodict.m main/comm/inst/shannonfanoenco.m
diffstat 4 files changed, 286 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/main/comm/inst/huffmandict.m	Mon Oct 02 06:22:48 2006 +0000
+++ b/main/comm/inst/huffmandict.m	Mon Oct 02 06:29:09 2006 +0000
@@ -75,6 +75,7 @@
     error("Usage: huffman_dict(source_prob,{togglecode 1-0 in code});")
   elseif nargin < 3
     togglecode=0;
+    minvar=0;
   elseif nargin < 4
     minvar=0;
   end
@@ -164,10 +165,6 @@
     I=I+1;
   end
 
-  one_cw="1";
-  zero_cw="0";
-
-
   if (togglecode==0)
       one_cw=1;
       zero_cw=0;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main/comm/inst/shannonfanodeco.m	Mon Oct 02 06:29:09 2006 +0000
@@ -0,0 +1,136 @@
+## (C) 2006, Sep 30, Muthiah Annamalai, <muthiah.annamalai@uta.edu>
+## 
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+##
+
+##
+## usage: sig=shannonfanodeco(hcode,dict)
+## The function returns the original signal that was 
+## Shannonfano encoded signal using shannonfanoenco. This function uses
+## a dict built from the shannonfanodict and uses it to decode a signal 
+## list into a shannonfano list.
+## Restrictions include hcode is expected to be a binary code;
+## returned signal set that strictly belongs in the range [1,N]
+## with N=length(dict). Also dict can  only be from the
+## shannonfanodict() routine. Whenever decoding fails,
+## those signal values are indicated by -1, and we successively 
+## try to restart decoding from the next bit that hasnt failed in 
+## decoding, ad-infinitum. 
+##
+## example: hd=shannonfanodict(1:4,[0.5 0.25 0.15 0.10])
+##          hcode=shannonfanoenco(1:4,hd) #  [ 1   0   1   0   0   0   0   0   1 ]
+##          shannonfanodeco(hcode,hd) # [1 2 3 4]
+## 
+function sig=shannonfanodeco(hcode,dict)
+  if ( nargin < 2 || strcmp(class(dict),"cell")~=1 )
+    error('usage: shannonfanoenco(sig,dict)');
+  end
+  if (max(hcode) > 1 || min(hcode) < 0)
+    error("hcode has elements that are outside alphabet set ...
+	Cannot decode.");
+  end
+  
+# TODO:
+# O(log(N)) algorithms exist, but we need some effort to implement those
+# Maybe sometime later, it would be a nice 1-day project
+# Ref: A memory efficient Shannonfano Decoding Algorithm, AINA 2005, IEEE
+#
+
+# TODO: Somebody can implement a 'faster' algorithm than O(N^3) at present
+# Decoding Algorithm O(N+k*log(N)) which is approximately O(N+Nlog(N))
+#
+# 1.  Separate the dictionary  by the lengths
+#     and knows symbol correspondence.
+#
+# 2.  Find the symbol in the dict of lengths l,h where
+#     l = smallest cw length ignoring 0 length CW, and
+#     h = largest cw length , with k=h-l+1;
+#     
+# 3.  Match the k codewords to the dict using binary
+#     search, and then you can declare decision.
+#
+# 4.  In case of non-decodable words skip the start-bit
+#     used in the previous case, and then restart the same
+#     procedure from the next bit.
+#
+  L=length(dict);
+  lenL=length(dict{1});
+  lenH=0;
+
+#  
+# Know the ranges of operation
+#  
+  for itr=1:L
+    t=length(dict{itr});
+    if(t < lenL)
+      lenL=t;
+    end
+    if(t > lenH)
+      lenH=t;
+    end
+  end
+
+#
+# Now do a O(N^4) algorithm
+#
+  itr=0; #offset into the hcode
+  sig=[]; #output
+  CL=length(hcode);
+
+  %whole decoding loop.
+  while ( itr <  CL )
+    %decode one element (or just try to).
+    for itr_y=lenL:lenH
+      %look for word in dictionary.
+      %with flag to indicate found 
+      %or not found. Detect end of buffer.
+    
+      if ( (itr+itr_y) > CL )
+	break;
+      end
+
+      word=hcode(itr+1:itr+itr_y);
+      flag=0;
+      
+      %word
+
+      %search loop.
+      for itr_z=1:L
+	if(isequal(dict{itr_z},word))
+	  itr=itr+itr_y; 
+	  sig=[sig itr_z];
+	  flag=1;
+	  break;
+	end
+      end %for_ loop breaker
+
+      if( flag == 1 )
+	break; %also need to break_ above then.
+      end
+
+    end %for_ loop
+
+
+    #could not decode
+    if( flag == 0 )
+      itr=itr+1;
+      sig=[sig -1]; 
+    end
+
+  end  %while_ loop
+end
+%! 
+%! assert(shannonfanodeco(shannonfanoenco(1:4, shannonfanodict(1:4,[0.5 0.25 0.15 0.10])), shannonfanodict(1:4,[0.5 0.25 0.15 0.10])), [1:4],0)
+%!
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main/comm/inst/shannonfanodict.m	Mon Oct 02 06:29:09 2006 +0000
@@ -0,0 +1,104 @@
+## (C) 2006, September 29, Muthiah Annamalai, <muthiah.annamalai@uta.edu>
+## 
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+##
+
+## usage: shannonfanodict(symbols,symbol_probabilites)
+##        computes the code words for the symbol probabilities using the
+##        shannon fano scheme. Output is a dictionary cell-array, which 
+##        are codewords, and correspond to the order of input probability.
+##
+##
+## example: CW=shannonfanodict(1:4,[0.5 0.25 0.15 0.1]);
+##          assert(redundancy(CW,[0.5 0.25 0.15 0.1]),0.25841,0.001)
+##
+function [cw_list]=shannonfanodict(symbol,P)
+  DMAX=length(P);
+  S=1:DMAX;
+#
+#FIXME: Is there any other way of doing the
+#topological sort? Insertion sort is bad.
+#
+#Sort the probability list in 
+#descending/non-increasing order.
+#Using plain vanilla insertion sort.
+#
+  for i=1:DMAX
+    for j=i:DMAX
+      
+      if(P(i) < P(j))
+	
+				#Swap prob
+	t=P(i);
+	P(i)=P(j);
+	P(j)=t;
+	
+				#Swap symb
+	t=S(i);
+	S(i)=S(j);
+	S(j)=t;
+      end
+      
+    end
+  end
+  
+  
+  #Now for each symbol you need to
+  #create code as first [-log p(i)] bits of
+  #cumulative function sum(p(1:i))
+  #
+  #printf("Shannon Codes\n");
+  #data_table=zeros(1,DMAX);
+
+   cw_list={};
+   for i=1:DMAX
+     if(P(i)>0)
+       digits=ceil(-log2(P(i))); #somany digits needed.
+     else
+       digits=0; #dont assign digits for zero probability symbols.
+     end
+     
+     Psum = sum([0 P](1:i)); #Cumulative probability
+     s=[];
+     for i=1:digits;
+       Psum=2*Psum;
+       if(Psum >= 1)
+	 s=[s 1];
+	 Psum=Psum-1;
+       else
+	 s=[s 0];
+       end       
+     end
+     cw_list{i}=s;
+   end
+   
+   #re-arrange the list accroding to input prob list.
+   cw_list2={};
+   for i=1:length(cw_list)
+     cw_list2{i}=cw_list{S(i)};
+   end
+   cw_list=cw_list2;
+
+   return;
+end
+
+%!
+%!CW=shannonfanodict(1:4,[0.5 0.25 0.15 0.1]);
+%!assert(redundancy(CW,[0.5 0.25 0.15 0.1]),0.057980,0.001)
+%!CW=shannonfanodict(1:4,[0.5 0.15 0.25 0.1]);
+%!P=[0.5 0.25 0.15 0.1 0];
+%!CW=shannonfanodict(1:5,P);
+%!redundancy(CW,P)
+%!
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main/comm/inst/shannonfanoenco.m	Mon Oct 02 06:29:09 2006 +0000
@@ -0,0 +1,45 @@
+## (C) 2006, Oct 1, Muthiah Annamalai, <muthiah.annamalai@uta.edu>
+## 
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+##
+
+##
+## usage:shannonfanoenco(sig,dict)
+## The function returns the Shannon Fano encoded signal using dict.
+## This function uses a dict built from the shannonfanodict
+## and uses it to encode a signal list into a shannon fano code.
+## Restrictions include a signal set that strictly belongs
+## in the range [1,N] with N=length(dict). Also dict can
+## only be from the shannonfanodict() routine.
+## 
+## 
+## example: hd=shannonfanodict(1:4,[0.5 0.25 0.15 0.10])
+##          shannonfanoenco(1:4,hd) #  [   0   1   0   1   1   0   1   1   1   0]
+##
+##
+function sf_code=shannonfanoenco(sig,dict)
+  if nargin < 2
+    error('usage: huffmanenco(sig,dict)');
+  end
+  if (max(sig) > length(dict)) || ( min(sig) < 1)
+    error("signal has elements that are outside alphabet set ...
+	Cannot encode.");
+  end
+  sf_code=[dict{sig}];
+  return
+end
+%! 
+%! assert(shannonfanoenco(1:4, shannonfanodict(1:4,[0.5 0.25 0.15 0.10])),[   0   1   0   1   1   0   1   1   1   0],0)
+%!