Skip to main content

A Python implementation of the tANS algorithm

Project description

tANS_py

Tabled Asymmetric Numeral Systems Implementation in Python. This code is available as a package on PyPI here.

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.2.tar.gz (11.5 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.2-py3-none-any.whl (12.2 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: tans_py-0.1.2.tar.gz
  • Upload date:
  • Size: 11.5 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.2.tar.gz
Algorithm Hash digest
SHA256 decce881d31d15fd9e9d133f68c5b62456520f21d5f949c8e93d6abcd88b4884
MD5 ff36d7930a6d8fd4194fc250759f5f49
BLAKE2b-256 5b3f06063835a5432a63127fa06b6080ae0fad98cb6372052a80e3e9251a3418

See more details on using hashes here.

File details

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

File metadata

  • Download URL: tans_py-0.1.2-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.2-py3-none-any.whl
Algorithm Hash digest
SHA256 9410f570995be09c3361b571c1ac21fe7d333e33068b33ce5ecb2dcde1b149a0
MD5 f621b7c2bda215a834f1df636b49245a
BLAKE2b-256 179c89549ee0a29eeeb4e29a1bea6697c5a6d908c81ebdade0e0522d5aebc028

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