Exemplo n.º 1
0
    def __init__(self, source):
        self.dtype = source.dtype
        self.ndim = len(source.shape)
        self.shape = source.shape
        self.size = product(self.shape)

        self._coord_index = np.array(
            [product(source.shape[axis + 1:]) for axis in range(self.ndim)])
        self._source = source
Exemplo n.º 2
0
def sort_coords(coords, shape):
    coord_index = np.array(
        [product(shape[axis + 1:]) for axis in range(len(shape))])

    shape = np.array(shape)
    blocks = []
    num_coords = 0
    while True:
        block = []

        while len(block) < PER_BLOCK:
            try:
                coord = next(coords)
                block.append(coord)
            except StopIteration:
                break

        if block:
            num_coords += len(block)
            offsets = np.sum(block * coord_index, 1)
            blocks.append(offsets)
        else:
            break

    for block in merge_sort(blocks):
        coords = (np.expand_dims(block, 1) // coord_index) % shape
        yield from coords
Exemplo n.º 3
0
    def constant(shape, dtype, value):
        assert isinstance(value, dtype)

        size = product(shape)

        blocks = [
            np.ones([PER_BLOCK], dtype) * value
            for _ in range(size // PER_BLOCK)
        ]
        if size % PER_BLOCK > 0:
            blocks.append(np.ones([size % PER_BLOCK], dtype) * value)

        return BlockListBase(shape, dtype, blocks)
Exemplo n.º 4
0
    def expand(self, new_shape):
        if not isinstance(self.accessor, SparseTable):
            raise NotImplementedError

        if len(new_shape) != len(self.shape):
            return ValueError
        elif not (np.array(new_shape) >= np.array(self.shape)).all():
            return ValueError

        self.accessor.shape = new_shape
        self.accessor.size = product(new_shape)

        self.shape = self.accessor.shape
        self.size = self.accessor.size
Exemplo n.º 5
0
    def __setitem__(self, match, value):
        match = validate_match(match, self.shape)

        if len(match) == self.ndim and all(isinstance(c, int) for c in match):
            index = sum(np.array(match) * self._coord_index)
            self._blocks[index // PER_BLOCK][index %
                                             PER_BLOCK] = self.dtype(value)
        else:
            update_shape = shape_of(self.shape, match)

            if isinstance(value, Tensor):
                if not isinstance(value, DenseTensor):
                    value = DenseTensor.from_sparse(value)

                if value.shape != update_shape:
                    value = value.broadcast(update_shape)
                value = list(iter(value))
            else:
                value = list(iter(value for _ in range(product(update_shape))))

            assert len(value) == product(update_shape)

            affected_coords = itertools.product(*affected(match, self.shape))
            for coords in chunk_iter(affected_coords, PER_BLOCK):
                indices = np.sum(coords * self._coord_index, 1)
                block_ids = indices // PER_BLOCK
                offsets = indices % PER_BLOCK
                for block_id in np.unique(block_ids):
                    num_values = np.sum(block_ids == block_id)
                    block_offsets = offsets[:num_values]
                    block_values = value[:num_values]
                    self._blocks[block_id][block_offsets] = np.array(
                        block_values)

                    offsets = offsets[num_values:]
                    value = value[num_values:]
Exemplo n.º 6
0
    def product(self, axis=None):
        if axis is None or (axis == 0 and self.ndim == 1):
            if self.all():
                return product(value for _, value in self.filled())
            else:
                return self.dtype(0)

        assert axis < self.ndim
        shape = list(self.shape)
        del shape[axis]
        multiplied = SparseTensor(shape, self.dtype)

        if axis == 0:
            for coord in self.filled_at(list(range(1, self.ndim))):
                multiplied[coord] = self[(slice(None), ) + coord].product()
        else:
            for prefix in self.filled_at(list(range(axis))):
                multiplied[prefix] = self[prefix].product(0)

        return multiplied
Exemplo n.º 7
0
    def __init__(self, shape, dtype, blocks=None):
        BlockList.__init__(self, shape, dtype)

        if blocks is None:
            blocks = [
                np.zeros([PER_BLOCK], dtype)
                for _ in range(self.size // PER_BLOCK)
            ]
            if self.size % PER_BLOCK > 0:
                blocks.append(np.zeros([self.size % PER_BLOCK], dtype))
        else:
            assert len(blocks) == math.ceil(self.size / PER_BLOCK)
            for block in blocks[:-1]:
                assert block.shape == (PER_BLOCK, )

            if self.size % PER_BLOCK:
                assert blocks[-1].shape == (self.size % PER_BLOCK, )

        self._blocks = blocks
        self._coord_index = np.array(
            [product(shape[axis + 1:]) for axis in range(self.ndim)])
Exemplo n.º 8
0
    def filled(self, match=None):
        assert list(self._left.filled(match)) == sorted(
            self._left.filled(match))
        assert list(self._right.filled(match)) == sorted(
            self._right.filled(match))

        left = self._left.filled(match)
        right = self._right.filled(match)

        left_done = False
        right_done = False

        left_next = None
        right_next = None

        coord_index = np.array([
            product(self.shape[axis + 1:]) for axis in range(len(self.shape))
        ])

        while True:
            if left_next is None:
                try:
                    left_next = next(left)
                except StopIteration:
                    left_done = True

            if right_next is None:
                try:
                    right_next = next(right)
                except StopIteration:
                    right_done = True

            if left_done and right_next:
                value = self._combinator(self._left.dtype(0), right_next[1])
                if value:
                    yield (right_next[0], value)
                    right_next = None

            if right_done and left_next:
                value = self._combinator(left_next[1], self._right.dtype(0))
                if value:
                    yield (left_next[0], value)
                    left_next = None

            if left_done or right_done:
                break
            else:
                (left_coord, left_value) = left_next
                (right_coord, right_value) = right_next
                left_index = np.sum(np.array(left_coord) * coord_index)
                right_index = np.sum(np.array(right_coord) * coord_index)

                if left_index == right_index:
                    left_next = None
                    right_next = None

                    value = self._combinator(left_value, right_value)
                    if value:
                        yield (left_coord, value)

                elif left_index < right_index:
                    left_next = None

                    value = self._combinator(left_value, self._right.dtype(0))
                    if value:
                        yield (left_coord, value)

                elif right_index < left_index:
                    right_next = None

                    value = self._combinator(self._left.dtype(0), right_value)
                    if value:
                        yield (right_coord, value)

                else:
                    raise RuntimeError

        if left_done and not right_done:
            for coord, right_value in right:
                value = self._combinator(self._left.dtype(0), right_value)
                if value:
                    yield (coord, value)

        elif right_done and not left_done:
            for coord, left_value in left:
                value = self._combinator(left_value, self._right.dtype(0))
                if value:
                    yield (coord, value)
Exemplo n.º 9
0
 def __init__(self, shape, dtype):
     self.dtype = dtype
     self.ndim = len(shape)
     self.shape = shape
     self.size = product(shape)