pasqal-io / Pulser

Library for pulse-level/analog control of neutral atom devices. Emulator with QuTiP.
Apache License 2.0
159 stars 57 forks source link

hotfix restrict scipy < 1.13 due to breaking Qutip #668

Closed awennersteen closed 2 months ago

awennersteen commented 2 months ago

The latest Scipy release broke the Pulser-Simulation module. Whilst looking for a solution, let's restrict the version.

Stack trace:

sequence = <pulser.sequence.sequence.Sequence object at 0x7f2c7f55ed40>

    def test_qutip_backend(sequence):
        sim_config = SimConfig()
        with pytest.raises(TypeError, match="must be of type 'EmulatorConfig'"):
            QutipBackend(sequence, sim_config)

>       qutip_backend = QutipBackend(sequence)

tests/test_qutip_backend.py:46: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
pulser-simulation/pulser_simulation/qutip_backend.py:50: in __init__
    self._sim_obj = QutipEmulator.from_sequence(
pulser-simulation/pulser_simulation/simulation.py:769: in from_sequence
    return cls(
pulser-simulation/pulser_simulation/simulation.py:156: in __init__
    self._hamiltonian = Hamiltonian(
pulser-simulation/pulser_simulation/hamiltonian.py:90: in __init__
    self.set_config(config)
pulser-simulation/pulser_simulation/hamiltonian.py:161: in set_config
    self._build_basis_and_op_matrices()
pulser-simulation/pulser_simulation/hamiltonian.py:331: in _build_basis_and_op_matrices
    self.basis[proj[0]] * self.basis[proj[1]].dag()
.venv/lib/python3.10/site-packages/qutip/qobj.py:497: in __mul__
    out.data = self.data * other.data
.venv/lib/python3.10/site-packages/scipy/sparse/_matrix.py:44: in __mul__
    return self._matmul_dispatch(other)
.venv/lib/python3.10/site-packages/scipy/sparse/_base.py:606: in _matmul_dispatch
    return self._matmul_sparse(other)
.venv/lib/python3.10/site-packages/scipy/sparse/_compressed.py:509: in _matmul_sparse
    other = self.__class__(other)  # convert to this format
.venv/lib/python3.10/site-packages/qutip/fastsparse.py:42: in __init__
    if args[1].shape[0] and args[1].dtype != np.int32:
.venv/lib/python3.10/site-packages/scipy/sparse/_index.py:52: in __getitem__
    row, col = self._validate_indices(key)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <1x2 sparse matrix of type '<class 'numpy.complex128'>'
    with 1 stored elements in Compressed Sparse Row format>, key = 1

    def _validate_indices(self, key):
        # First, check if indexing with single boolean matrix.
        from ._base import _spbase
        if (isinstance(key, (_spbase, np.ndarray)) and
                key.ndim == 2 and key.dtype.kind == 'b'):
            if key.shape != self.shape:
                raise IndexError('boolean index shape does not match array shape')
            row, col = key.nonzero()
        else:
            row, col = _unpack_index(key)
        M, N = self.shape

        def _validate_bool_idx(
            idx: npt.NDArray[np.bool_],
            axis_size: int,
            axis_name: str
        ) -> npt.NDArray[np.int_]:
            if len(idx) != axis_size:
                raise IndexError(
                    f"boolean {axis_name} index has incorrect length: {len(idx)} "
                    f"instead of {axis_size}"
                )
            return _boolean_index_to_array(idx)

        if isintlike(row):
            row = int(row)
            if row < -M or row >= M:
>               raise IndexError('row index (%d) out of range' % row)
E               IndexError: row index (1) out of range

.venv/lib/python3.10/site-packages/scipy/sparse/_index.py:180: IndexError