Python program for Shannon-Fano Coding Algorithm | Python
In this we are going to see Shannon-Fano Coding Algorithm using python.

from symtable import Symbol
import math


class node:
    def __init__(self):
        self.sym = ''
        self.pro = 0.0
        self.arr = [0]*20
        self.top = 0


p = [node() for _ in range(20)]


def shannon(l, h, p):
    pack1 = 0
    pack2 = 0
    diff1 = 0
    diff2 = 0
    if (l + 1) == h or l == h or l > h:
        if l == h or l > h:
            return
        p[h].top += 1
        p[h].arr[p[h].top] = 0
        p[l].top += 1
        p[l].arr[p[l].top] = 1

        return

    else:
        for i in range(l, h):
            pack1 = pack1 + p[i].pro
        pack2 = pack2 + p[h].pro
        diff1 = pack1 - pack2
        if diff1 < 0:
            diff1 = diff1 * -1
        j = 2
        while j != h - l + 1:
            k = h - j
            pack1 = pack2 = 0
            for i in range(l, k+1):
                pack1 = pack1 + p[i].pro
            for i in range(h, k, -1):
                pack2 = pack2 + p[i].pro
            diff2 = pack1 - pack2
            if diff2 < 0:
                diff2 = diff2 * -1
            if diff2 >= diff1:
                break
            diff1 = diff2
            j += 1

        k += 1
        for i in range(l, k+1):
            p[i].top += 1
            p[i].arr[p[i].top] = 1

        for i in range(k + 1, h+1):
            p[i].top += 1
            p[i].arr[p[i].top] = 0

        shannon(l, k, p)
        shannon(k + 1, h, p)


def sortByProbability(n, p):
    temp = node()
    for j in range(1, n):
        for i in range(n - 1):
            if p[i].pro > p[i + 1].pro:
                temp.pro = p[i].pro
                temp.sym = p[i].sym

                p[i].pro = p[i + 1].pro
                p[i].sym = p[i + 1].sym

                p[i + 1].pro = temp.pro
                p[i + 1].sym = temp.sym


global dataLen
dataLen = {}


def display(n, p):
    print("\n\nSymbol\tProbability\tCode", end='')
    for i in range(n - 1, -1, -1):
        print("\n", p[i].sym, "\t", p[i].pro, "\t\t", end='')
        for j in range(p[i].top+1):
            print(p[i].arr[j], end='')
            dataLen[p[i].sym] = p[i].top+1


def calculateEntropy(n, p):
    entropy = 0.0
    for i in range(n):
        entropy = entropy + (p[i].pro * math.log2(1 / p[i].pro))
    return round(entropy, 3)


def averageCodeLength(data, p):
    x = []
    for i in dataLen.values():
        x.append(i)
    x.reverse()
    codeLength = 0
    for i in range(len(x)):
        codeLength = codeLength + (p[i].pro * x[i])
    return codeLength


def calculateCodeEfficiency(entropy, codeLength):
    codeEfficiency = (entropy / codeLength)*100
    return round(codeEfficiency, 3)


total = 0
data = []
n = int(input("\n\nEnter the number of symbols: "))

for i in range(0, n):
    p[i].sym = 's' + str(i+1)
    print("Enter the probability of", p[i].sym, ": ", end='')
    probability = float(input())
    data.append(probability)
    assert(probability >= 0.0 and probability <= 1.0)


for i in range(n):
    p[i].pro = data[i]
    total = total + p[i].pro

    if (total > 1):
        print("Invalid. Enter new values")
        total = total - p[i].pro
        i -= 1

i += 1
p[i].pro = 1 - total
sortByProbability(n, p)

for i in range(n):
    p[i].top = -1

shannon(0, n - 1, p)
display(n, p)

print("\n\nShannon Fano Entropy is: ", calculateEntropy(n, p))
print("\nAverage Code Length is: ", averageCodeLength(data, p))
print("\nCode Efficiency is: ", calculateCodeEfficiency(
    calculateEntropy(n, p), averageCodeLength(data, p)), "%\n\n")


#ENJOY CODING


Post a Comment

FOR ANY DOUBTS AND ERRORS FEEL FREE TO ASK. YOUR DOUBTS WILL BE ADDRESSED ASAP

Previous Post Next Post