Skip to content

tensor

Tensor

Bases: FTyped[TensorFType[FT]], ABC

Abstract base class for tensor-like data structures. Tensors are multi-dimensional arrays that can be used to represent data in various formats. They support operations such as indexing, slicing, and reshaping, and can be used in mathematical computations. This class provides the basic interface for tensors to be used with lazy ops in Finch, though more advanced interfaces may be required for different backends.

Source code in src/finch/algebra/tensor.py
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
class Tensor(FTyped[TensorFType[FT]], ABC):
    """
    Abstract base class for tensor-like data structures. Tensors are
    multi-dimensional arrays that can be used to represent data in various
    formats. They support operations such as indexing, slicing, and reshaping,
    and can be used in mathematical computations. This class provides the basic
    interface for tensors to be used with lazy ops in Finch, though more
    advanced interfaces may be required for different backends.
    """

    @property
    def ndim(self) -> int:
        """Number of dimensions of the tensor."""
        return int(self.ftype.ndim)

    @property
    def size(self):
        size = 1
        for dim in self.shape:
            size *= int(dim)
        return size

    @property
    @abstractmethod
    def ftype(self) -> TensorFType[FT]:
        """FType of the tensor, which may include metadata about the tensor."""
        ...

    @property
    def fill_value(self) -> Any:
        """The fill value for the tensor.  The fill value is the
        default value for a tensor when it is created with a given shape and dtype,
        as well as the background value for sparse tensors.
        Note: this is the raw value NOT the AbstractFill. A tensor whose fill is
        dynamic holds its own fill value.
        """
        fill_type = self.ftype.fill_type
        if is_static(fill_type):
            return fill_type.value
        raise NotImplementedError(
            f"{type(self).__name__} must hold its dynamic fill value"
        )

    @property
    def fill(self) -> AbstractFill:
        """
        The fill of the tensor: its fill value, and whether kernels may
        specialize on it. Its ftype is the fill of the tensor's format.
        """
        fill_type = self.ftype.fill_type
        if is_static(fill_type):
            return StaticFill(fill_type.value)
        return DynamicFill(self.fill_value, fill_type.element_type)

    def with_fill(self, fill_value: AbstractFill) -> Tensor:
        """
        An equivalent tensor carrying `fill_value` as its fill.
        """
        raise NotImplementedError(
            f"{type(self).__name__} cannot replace its fill value"
        )

    @property
    def element_type(self) -> FT:
        """The element type of the tensor.  The element type is the scalar type of
        the elements in a tensor, which may be different from the data type of the
        tensor.
        """
        return self.ftype.element_type

    @property
    def dtype(self):
        return self.element_type

    @property
    def device(self):
        return getattr(self, "_device", self.ftype.device)

    @property
    def device_type(self) -> FType:
        return self.ftype.device_type

    def to_device(self, device, /, *, stream=None):
        if stream is not None:
            raise ValueError(f"stream argument is not supported; got {stream!r}")
        device = normalize_device(device)
        if device == self.device:
            return self
        raise ValueError(f"device argument is not supported; got {device!r}")

    @property
    def shape_type(self) -> tuple[FType, ...]:
        """Shape type of the tensor. The shape type is a tuple of the index
        types in the tensor. It's the type of each element in tns.shape. It
        should be an actual tuple, rather than a tupleftype, so that it can hold
        e.g. dtypes, formats, or types, and so that we can easily index it."""
        return self.ftype.shape_type

    @property
    @abstractmethod
    def shape(self) -> tuple[np.intp, ...]:
        """Shape of the tensor."""
        ...

    @abstractmethod
    def item(self):
        """
        Return the Python scalar stored in a zero-dimensional tensor.

        Indexing tensor objects must keep returning tensor-like values, including for
        zero-dimensional results. `item()` is the explicit escape hatch for code that
        needs the underlying Python scalar value. Implementations should raise
        `ValueError` when called on a non-scalar tensor.
        """
        ...

    @abstractmethod
    def to_numpy(self):
        """Convert the tensor to a NumPy representation."""
        ...

    @abstractmethod
    def to_scipy(self):
        """Convert the tensor to a SciPy sparse representation."""
        ...

element_type property

The element type of the tensor. The element type is the scalar type of the elements in a tensor, which may be different from the data type of the tensor.

fill property

The fill of the tensor: its fill value, and whether kernels may specialize on it. Its ftype is the fill of the tensor's format.

fill_value property

The fill value for the tensor. The fill value is the default value for a tensor when it is created with a given shape and dtype, as well as the background value for sparse tensors. Note: this is the raw value NOT the AbstractFill. A tensor whose fill is dynamic holds its own fill value.

ftype abstractmethod property

FType of the tensor, which may include metadata about the tensor.

ndim property

Number of dimensions of the tensor.

shape abstractmethod property

Shape of the tensor.

shape_type property

Shape type of the tensor. The shape type is a tuple of the index types in the tensor. It's the type of each element in tns.shape. It should be an actual tuple, rather than a tupleftype, so that it can hold e.g. dtypes, formats, or types, and so that we can easily index it.

item() abstractmethod

Return the Python scalar stored in a zero-dimensional tensor.

Indexing tensor objects must keep returning tensor-like values, including for zero-dimensional results. item() is the explicit escape hatch for code that needs the underlying Python scalar value. Implementations should raise ValueError when called on a non-scalar tensor.

Source code in src/finch/algebra/tensor.py
209
210
211
212
213
214
215
216
217
218
219
@abstractmethod
def item(self):
    """
    Return the Python scalar stored in a zero-dimensional tensor.

    Indexing tensor objects must keep returning tensor-like values, including for
    zero-dimensional results. `item()` is the explicit escape hatch for code that
    needs the underlying Python scalar value. Implementations should raise
    `ValueError` when called on a non-scalar tensor.
    """
    ...

to_numpy() abstractmethod

Convert the tensor to a NumPy representation.

Source code in src/finch/algebra/tensor.py
221
222
223
224
@abstractmethod
def to_numpy(self):
    """Convert the tensor to a NumPy representation."""
    ...

to_scipy() abstractmethod

Convert the tensor to a SciPy sparse representation.

Source code in src/finch/algebra/tensor.py
226
227
228
229
@abstractmethod
def to_scipy(self):
    """Convert the tensor to a SciPy sparse representation."""
    ...

with_fill(fill_value)

An equivalent tensor carrying fill_value as its fill.

Source code in src/finch/algebra/tensor.py
159
160
161
162
163
164
165
def with_fill(self, fill_value: AbstractFill) -> Tensor:
    """
    An equivalent tensor carrying `fill_value` as its fill.
    """
    raise NotImplementedError(
        f"{type(self).__name__} cannot replace its fill value"
    )

TensorFType

Bases: FType, ABC, Generic[FT]

Source code in src/finch/algebra/tensor.py
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
class TensorFType(FType, ABC, Generic[FT]):
    @property
    def ndim(self) -> int:
        """Number of dimensions of the tensor."""
        return len(self.shape_type)

    @property
    def shape(self) -> tuple[int, ...]:
        raise TypeError("TensorFType does not have a shape.")

    @property
    def size(self) -> int:
        return functools.reduce(lambda x, y: x * int(y), self.shape, 1)

    @property
    @abstractmethod
    def fill_type(self) -> AbstractFillFType:
        """The fill of the format, either static or dynamic."""
        ...

    def with_fill(self, fill_type: AbstractFillFType) -> TensorFType:
        """
        This ftype carrying `fill_type` as its fill.
        """
        raise NotImplementedError(
            f"{type(self).__name__} cannot replace its fill value"
        )

    @property
    @abstractmethod
    def element_type(self) -> FT:
        """Data type of the tensor elements."""
        ...

    @property
    def dtype(self):
        return self.element_type

    @property
    def device(self):
        return serial()

    @property
    def device_type(self) -> FType:
        return self.device.ftype

    @property
    @abstractmethod
    def shape_type(self) -> tuple[FType, ...]:
        """Shape type of the tensor. The shape type is a tuple of the index
        types in the tensor. It's the type of each element in tns.shape. It
        should be an actual tuple, rather than a tuple type, so that it can hold
        e.g. dtypes, formats, or types, and so that we can easily index it."""
        ...

    @abstractmethod
    def construct(self, shape: tuple) -> Tensor:
        """
        Create a tensor instance with the given shape.

        Args:
            shape: The shape of the tensor to create.
        Returns:
            A tensor instance with the specified shape.
        """
        ...

    @abstractmethod
    def from_numpy(self, arr: np.ndarray) -> Tensor: ...

element_type abstractmethod property

Data type of the tensor elements.

fill_type abstractmethod property

The fill of the format, either static or dynamic.

ndim property

Number of dimensions of the tensor.

shape_type abstractmethod property

Shape type of the tensor. The shape type is a tuple of the index types in the tensor. It's the type of each element in tns.shape. It should be an actual tuple, rather than a tuple type, so that it can hold e.g. dtypes, formats, or types, and so that we can easily index it.

construct(shape) abstractmethod

Create a tensor instance with the given shape.

Parameters:

Name Type Description Default
shape tuple

The shape of the tensor to create.

required

Returns: A tensor instance with the specified shape.

Source code in src/finch/algebra/tensor.py
89
90
91
92
93
94
95
96
97
98
99
@abstractmethod
def construct(self, shape: tuple) -> Tensor:
    """
    Create a tensor instance with the given shape.

    Args:
        shape: The shape of the tensor to create.
    Returns:
        A tensor instance with the specified shape.
    """
    ...

with_fill(fill_type)

This ftype carrying fill_type as its fill.

Source code in src/finch/algebra/tensor.py
54
55
56
57
58
59
60
def with_fill(self, fill_type: AbstractFillFType) -> TensorFType:
    """
    This ftype carrying `fill_type` as its fill.
    """
    raise NotImplementedError(
        f"{type(self).__name__} cannot replace its fill value"
    )