Error in Numba function: "tuple index out of range" when using custom class for sparse matrix

87 Views Asked by At

I'm encountering an issue with a Numba-optimized function that involves a custom class for representing a sparse matrix. The error message I'm getting is:

numba.core.errors.TypingError: Failed in nopython mode pipeline (step: nopython frontend)
tuple index out of range
During: typing of static-get-item at z:\2023-2024\Python Labs\E0\TEST\Untitled-3.py (73)

File "z:\2023-2024\Python Labs\E0\TEST\Untitled-3.py", line 73:
def numba_csc_ndarray_dot2(a: csc_matrix, b: np.ndarray):
out = np.zeros((a.shape[0], b.shape[1]))
^

The problem seems to be related to indexing tuples, and it occurs in the following code snippet:

class csc_matrix:
    def __init__(self, data: np.array, indices: np.array, indptr: np.array, shape: tuple):
        self.data = data
        self.indices = indices
        self.indptr = indptr
        self.shape = [email protected](nopython=True)

class MatrixType(types.Type):
    def __init__(self, dtype):
        self.dtype = dtype
        self.data = types.Array(self.dtype, 1, 'C')
        self.indices = types.Array(types.int64, 1, 'C')
        self.indptr = types.Array(types.int64, 1, 'C')
        self.shape = types.UniTuple(types.int64, 2)
        super(MatrixType, self).__init__('csc_matrix')

@typeof_impl.register(csc_matrix)
def typeof_matrix(val, c):
    data = typeof_impl(val.data, c)
    return MatrixType(data.dtype)

@register_model(MatrixType)
class MatrixModel(models.StructModel):
    def __init__(self, dmm, fe_type):
        members = [('data', fe_type.data),('indices', fe_type.indices),('indptr', fe_type.indptr),('shape', fe_type.shape),]
        models.StructModel.__init__(self, dmm, fe_type, members)

make_attribute_wrapper(MatrixType, 'data', 'data')
make_attribute_wrapper(MatrixType, 'indices', 'indices')
make_attribute_wrapper(MatrixType, 'indptr', 'indptr')
make_attribute_wrapper(MatrixType, 'shape', 'shape')

def make_matrix(context, builder, typ, **kwargs):
    return cgutils.create_struct_proxy(typ)(context, builder, **kwargs)

@unbox(MatrixType)
def unbox_matrix(typ, obj, c):
    data = c.pyapi.object_getattr_string(obj, 'data')
    indices = c.pyapi.object_getattr_string(obj, 'indices')
    indptr = c.pyapi.object_getattr_string(obj, 'indptr')
    shape = c.pyapi.object_getattr_string(obj, 'shape')
    matrix = make_matrix(c.context, c.builder, typ)
    matrix.data = c.unbox(typ.data, data).value
    matrix.indices = c.unbox(typ.indices, indices).value
    matrix.indptr = c.unbox(typ.indptr, indptr).value
    matrix.shape = c.unbox(typ.shape, shape).value
    for att in [data, indices, indptr, shape]:
        c.pyapi.decref(att)
    is_error = cgutils.is_not_null(c.builder, c.pyapi.err_occurred())

    return NativeValue(matrix._getvalue(), is_error=is_error)

@box(MatrixType)
def box_matrix(typ, val, c):
    matrix = make_matrix(c.context, c.builder, typ)
    classobj = c.pyapi.unserialize(c.pyapi.serialize_object(csc_matrix))
    data_obj = c.box(typ.data, matrix.data)
    indices_obj = c.box(typ.indices, matrix.indices)
    indptr_obj = c.box(typ.indptr, matrix.indptr)
    shape_obj = c.box(typ.shape, matrix.shape)
    matrix_obj = c.pyapi.call_function_objargs(classobj, (data_obj, indices_obj, indptr_obj, shape_obj))
    return matrix_obj

def numba_csc_ndarray_dot2(a: csc_matrix, b: np.ndarray):

    out = np.zeros((a.shape[0], b.shape[1]))   

    for j in range(b.shape[1]):
        for i in range(b.shape[0]):
            for k in range(a.indptr[i], a.indptr[i + 1]):
                out[a.indices[k], j] += a.data[k] * b[i, j]

rows, cols = 100, 100
density = 0.1
sparse_coo = random(rows, cols, density=density, format='coo')
data = sparse_coo.data
indices = sparse_coo.row
indptr = sparse_coo.col
shape = (rows, cols)
matrix_A = csc_matrix(sparse_coo.data, sparse_coo.row, sparse_coo.col, shape=(rows, cols))

vector_b = np.random.rand(cols)

solution_x =numba_csc_ndarray_dot2(matrix_A,vector_b )


print("Matrix A:")
print(matrix_A.toarray())
print("\nVector b:")
print(vector_b)
print("\nSolution x:")
print(solution_x)

I suspect that either a.indices[k] or a.data[k] is resulting in a tuple, causing the "tuple index out of range" error. I've added some debugging print statements, and the output indicates unexpected tuple values.

I'd appreciate any insights or suggestions on how to resolve this issue.

0

There are 0 best solutions below