diff --git a/releasenotes/notes/mps-apply_multi_qubit_gate-crash-23d26d405f80163d.yaml b/releasenotes/notes/mps-apply_multi_qubit_gate-crash-23d26d405f80163d.yaml new file mode 100644 index 0000000000..1df3c6c3ab --- /dev/null +++ b/releasenotes/notes/mps-apply_multi_qubit_gate-crash-23d26d405f80163d.yaml @@ -0,0 +1,11 @@ +--- +prelude: > + MPS::apply_multi_qubit_gate could crash in some circumstances +fixes: + - | + A matrix was attempted to be constructed despite having `is_diagonal` + parameter set to true and the passed matrix being a vector. The attempt + to access the element incorrectly resulted in a crash. Now a vector is + constructed when `is_diagonal` is true. For more information refer to + `#2292 ` + diff --git a/src/simulators/matrix_product_state/matrix_product_state_internal.cpp b/src/simulators/matrix_product_state/matrix_product_state_internal.cpp index 6b2d117689..e76dfb5d60 100644 --- a/src/simulators/matrix_product_state/matrix_product_state_internal.cpp +++ b/src/simulators/matrix_product_state/matrix_product_state_internal.cpp @@ -789,13 +789,22 @@ void MPS::apply_multi_qubit_gate(const reg_t &qubits, const cmatrix_t &mat, // change qubit order in the matrix - instead of doing swaps on the qubits uint_t nqubits = qubits.size(); uint_t sidelen = 1 << nqubits; - cmatrix_t new_mat(sidelen, sidelen); - for (uint_t col = 0; col < sidelen; ++col) { - for (uint_t row = 0; row < sidelen; ++row) { - if (row == col) - new_mat(new_vec[row], new_vec[row]) = mat(row, row); - else + cmatrix_t new_mat(is_diagonal ? 1 : sidelen, sidelen); + + if (is_diagonal) { + for (uint_t col = 0; col < sidelen; ++col) { + new_mat(0, new_vec[col]) = + mat.GetRows() == 1 + ? mat(0, col) + : mat(col, + col); // this is just in case something passes a matrix + // instead of a vector even if is_diagonal is true + } + } else { + for (uint_t col = 0; col < sidelen; ++col) { + for (uint_t row = 0; row < sidelen; ++row) { new_mat(new_vec[row], new_vec[col]) = mat(row, col); + } } }