Wednesday, February 2, 2022

Counting Arithmetic Operators in Python

counting arithmetic operators

Counting arithmetic operations in Python

1. Define a class of operators with counter

A simple and non-invasive solution is to define a new class of operator taking numpy.adarray as arguments and then define a counter inside that operator.

import numpy as np 

class Operator:

    complexity = 0 # global counter

    def __init__(self):
        self._add = 0 # local counter 

    def add(self, x, y):
        assert x.shape == y.shape 
        self._add += x.size 
        return x+y 

    def save(self):
        Operator.complexity += self._add

def func1():
    x = np.array([1,2])
    op = Operator() 
    y = op.add(x, x)
    op.save()
    print(f"number of additions just performed = {op._add} complexity={Operator.complexity}")

func1()
func1()

we should get

number of additions just performed = 2 complexity=2
number of additions just performed = 2 complexity=4

2. Subclassing using ndarray

We now construct a class called ndarrayExt such that

  • All the methods of numpy is applicable on our class.
  • When we perform the addition operators, the number of operators is cumulatively recorded.

This can be done using Subclassing ndarray. See StackOverFlow.

Note that this method need to redefine the magic methods, e.g. __add__ the addition method. So should be super careful when implement it.

Here is a simple template.

import numpy as np

class ndarrayExt(np.ndarray):

    nb_add = 0

    def __new__(cls, values):
        self = np.asarray(values).view(cls)
        return self 

    def __add__(self, new_numbers):
        ndarrayExt.nb_add += self.size
        return np.ndarray.__add__(self,new_numbers)

a = ndarrayExt([1,2,3,4])
b = ndarrayExt([1,1,1,1])

# Check the first property: the sum() method of ndarray is maintained in our class
print(f"Sum of a = {a.sum()}") # get 10

# Check the second property: cumulatively record the number of addition operators
c = a+b+b
print(f"Number of additions has been used = {ndarrayExt.nb_add}") # get 8

Note. In above code, if we use c=1+a+b+b instead, then we still get 8 as a result of print(ndarrayExt.nb_add) since the number 1 is not in our class and its addition is therefore not recorded. So the order of addition is very importance.

Popular Posts