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.