Skip to main content

A Python implementation of the tANS algorithm

Project description

tANS_py

Tabled Asymmetric Numeral Systems Implementation in Python.

Asymmetric Numeral Systems (ANS) is a Entropy Coding compression technique created by Jarek Duda. This repository contains a Python implementation a version of the techinque that uses lookup table to store the state transitions (called tANS).

This implementation is based on the following resources:

  • The original paper Asymmetric Numeral Systems by Jarek Duda
  • Slides from a course taught by Duda (see slide 38)
  • The following medium article
  • This python implementation of tANS
    • My implementation is very similar to this code, but is written to be more readable and fixes some of the small bugs in the original code
  • This blog post explaining ANS

Limitations

This implementation is not optimized for speed. It is meant to be a simple implementation that is easy to understand.

The main limitation of this implementation is that L, the table size, must be a power of 2.

Usage

See example.ipynb for examples of all the things discussed below.

Coder

This is the main class that is used to encode and decode data. It is initialized with the table length (L), the list of symbols (s_list) and the list of frequencies (L_s). See implemention in Coder.py.

Example Usage:

# importing the Coder class as well as the Utils module, which helps with generating random data for testing
import tANS_py.Coder, tANS_py.Utils
import numpy as np

# Set up the alphabet
s = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]
nbits = 5 # 5 bits per symbol as there are 26 symbols in the alphabet

# Run this multiple times to see how it performs on average
comp_ratios = []
for i in range(50):
    # Set up random frequencies
    # This specifically generates a list of len(s) numbers randomly chosen between 1 and 100
    freq = tANS_py.Utils.generate_random_list2(len(s), 100)

    # Create the Coder object
    c = tANS_py.Coder.Coder(sum(freq), s, freq, fast = False) # specifies fast = False to use slower, but more effecient spread function

    # Create a message
    # Specifically generates a random string using symbols from s with frequencies from freq
    msg = tANS_py.Utils.generate_random_string(s, freq)

    # Encode and decode the message and get the number of bits of the encoded message
    # Note: you must pass in message as a list of symbols
    out, bits = c.encode_decode(list(msg))

    # Check if the decoding worked
    if "".join(out) != msg:
        # If the decoding failed, print a message
        print("Coding failed")
    else:
        # If the decoding worked, save the compression ratio
        comp_ratios.append(len(msg) * nbits / bits)
    
print("Comp Ratio:", np.mean(comp_ratios))

Output:

Comp Ratio: 1.359817660857606

Submodules of Coder

DecodeTable

This class is used to decode an encoded message. It is initialized with the table length (L), the list of symbols (s_list) and the list of frequencies (L_s). See implemention in Decoder.py

Encoder

This class is used to encode a message. It is initialized with the table length (L), the list of symbols (s_list) and the list of frequencies (L_s). See implemention in Encoder.py

Example Usage of Submodules:

# Testing code 
import tANS_py.Decoder
import tANS_py.Encoder

# Define the alphabet and the frequency of each symbol
s = ["A","B","C"]
freq = [6, 2, 24] # note that the sum of freq must be a power of 2 (in this case 32)

# Create the encoder and decoder
t = tANS_py.Decoder.DecodeTable(sum(freq), s, freq, fast = False)
g = tANS_py.Encoder.Encoder(sum(freq), s,freq,t.symbol_spread)

# Create message
msg = "CAACACCCCCCCCBCCCACCCACCCACCCBCC"
msg_temp = list(msg)

# Encode message
bit = g.encode(msg_temp)

# Decode message
out = t.decode(bit)
out.reverse() # reverse the list to get the original message, as the decoding function returns the message in reverse order
print("Coding worked:", "".join(out) == msg)

Output:

Coding worked: True

SpreadFunction.py

This module contains the spread function defined in the original paper. It is automatically called by Coder and its submodules. See implemention in SpreadFunction.py.

Utils.py

Contains utility functions for generating random data or rescaling frequencies for the coder. See implemention in Utils.py.

Functions:

from tANS_py import Utils
# generates a list of length numbers that sum to a power of 2, with each number being randomly chosen between 1 and n
Utils.generate_random_list_pow2(length, n) 

# generates a list of length numbers that sum to a target sum, with each number being randomly chosen between 1 and n
Utils.generate_random_list_target(length, n, target_sum)

# rescales a list of numbers to sum to a power of 2 that is less than or equal to max sum
Utils.rescale_list_to_power_of_2(input_list, max_sum)

# generates a random string of length n using symbols from s with frequencies from freq
Utils.generate_random_string(s, freq)

About

This implementation was created by Adam Taback as part of a research project at the University of Toronto, aiming to use ANS to compress neural network traces.

If you have any questions, reach out to me at adamrtaback@gmail.com.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tans_py-0.1.1.tar.gz (11.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

tans_py-0.1.1-py3-none-any.whl (12.2 kB view details)

Uploaded Python 3

File details

Details for the file tans_py-0.1.1.tar.gz.

File metadata

  • Download URL: tans_py-0.1.1.tar.gz
  • Upload date:
  • Size: 11.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.1.1 CPython/3.12.4

File hashes

Hashes for tans_py-0.1.1.tar.gz
Algorithm Hash digest
SHA256 ee87233a43adc5ff6111d6628fc32abac162d6862031a1955c39da0e2d928fe5
MD5 9c1062a6faac84b906d1acace22683df
BLAKE2b-256 cb4e5ac509a091932d13459d75aee5ff3006df6ed1d920409ab625645ebf2458

See more details on using hashes here.

File details

Details for the file tans_py-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: tans_py-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 12.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.1.1 CPython/3.12.4

File hashes

Hashes for tans_py-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 4df5499046fb28dd6220c76a45c2da24bc7439ebd3eab44ae20f50819714a851
MD5 2658e7c05f5ebc2e048391c3205ad39a
BLAKE2b-256 4678473dec3ccf7d1ef46e5601ae9951c15df0d16f89e97e0c0041af665a28ed

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page