Home > Software engineering >  Change array attribute
Change array attribute

Time:08-07

I need to compare two matrices, built using two different functions.

a=csr_matrix(M) (scipy function)
b=SparseMatrix(M) (My own function)

If I print 'a' and 'b' I get:

[[10. 20.  0.  0.  0.  0.]
 [ 0. 30. 99. 40.  0.  0.]
 [ 0.  0. 50. 60. 70.  0.]
 [ 0.  0.  0.  0.  0. 80.]]
[[10. 20.  0.  0.  0.  0.]
 [ 0. 30. 99. 40.  0.  0.]
 [ 0.  0. 50. 60. 70.  0.]
 [ 0.  0.  0.  0.  0. 80.]]

ie. the identical matrix.

BUT!: If I do

print(a==b)

it returns 'false'

Now,

print(a.dtype) = float64 
print(b.dtype) = 'SparseMatrix' object has no attribute 'dtype'.

I'm guessing this difference in regard to the type is the reason the boolean returns false?

Is there a smooth way to overcome this problem? - Preferably without changing 'SparseMatrix'.

Edit: Here is 'SparseMatrix':

class SparseMatrix:
    
    def __init__(self, A, tol = 1e-8):
        """
        

        Parameters
        ----------
        A : Numpy.Array
            Input matrix.
        tol : float, optional
            Tolerance for what is to be considered equal to 0. The default is 1e-8.

        Returns
        -------
        None.

        """
        self.n_rows = A.shape[0]
        self.n_cols = A.shape[1]
        self.intern_represent = 'CSR'
        self.tol = tol
        self.V = []
        self.col_index = [] 
        self.row_index = zeros(self.n_rows   1, dtype = int) 
        self.number_of_nonzero = 0
        
        for row in range(self.n_rows):
            self.row_index[row] = self.number_of_nonzero 
            for column in range(self.n_cols):
                if abs(A[row, column]) >= tol:
                    self.number_of_nonzero  = 1
                    self.V.append(A[row, column])
                    self.col_index.append(column)
        self.row_index[-1] = self.number_of_nonzero

CodePudding user response:

The reason a==b is False is because a and b are clearly different things. Yes, they might contain all the same values. However, everything else about them is different: One is a scipy csr_matrix and the other is a custom object, an instance of SparseMatrix that you wrote yourself. They are completely different objects, with a different underlying structure, different variables and methods, different data structure, and exist in different parts of the computer's memory.

The documentation on comparisons such as the == operator tells us that:

The default behavior for equality comparison (== and !=) is based on the identity of the objects. Hence, equality comparison of instances with the same identity results in equality, and equality comparison of instances with different identities results in inequality.

What this says is that, for arbitrary objects (i.e. not special types like numbers) == will only be True if you are comparing the same object to itself. Like doing a==a or b==b. It goes on to say:

The behavior of the default equality comparison, that instances with different identities are always unequal, may be in contrast to what types will need that have a sensible definition of object value and value-based equality. Such types will need to customize their comparison behavior, and in fact, a number of built-in types have done that.

I.e. for custom classes/objects, the only way for == to work is if the creator of the class (you) teaches python how to compare it to other things.

There lies your solution of what to do. If you want the class you have created, SparseMatrix, to be able to be compared with a csr_matrix, you need to implement that yourself.

The way to do this is by implementing specially-named methods in your SparseMatrix class, such as __eq__. You can look at the this StackOverflow thread as well as the documentation or some tutorials.

As an example:

class SparseMatrix:

    def __eq__(self, other):
        # When we are comparing with numpy arrays:
        if isinstance(other, np.array):

            # The dimensions have to be the same
            if other.shape[0] != self.n_rows or other.shape[1] != self.n_cols:
                return False
            
            # And the values have to be all the same
            # Return False the first time we find an unequal value
            for row in range(self.n_rows):
                for col in range(self.n_cols):
                    if self.V[row, col] != other[row, col]:
                        return False
            return True

CodePudding user response:

Probably not the most effective solution, but I would just use a for loop on both matrixes and compare them to each other.

CodePudding user response:

It all depends on how your custom function constructed the matrix. For, csr_matrix creates a matrix object which has a dtype property. If your function operates by constructing a three-dimensional array, for example, that resembles a sparse matrix, then that means that they are different types of objects.

You can check if they are of the same type by using print(type(a)) and print(type(a)). I would check that first and then proceed in comparing them not by their properties, which they obviously don't share, but by a for loop of their content (probably using the all() function).

  • Related