Skip to content

Commit

Permalink
Fix Exp on qubit arrays larger than 2 with single PauliI
Browse files Browse the repository at this point in the history
This fixes a bug in the decomposition for `Exp` that would cause a runtime failure if an array of more than two qubits was used and a single `PauliI` was passed in the Pauli array. The decomposition ignores `PauliI` by calling the `RemovePauliI` helper function, but then incorrectly uses the original arrays when rather than the filtered arrays in the rest of the operation. This adds a test to confirm the fix (without the fix the test triggers a runtime failure in `MapPauli`).
  • Loading branch information
swernli committed Jan 2, 2025
1 parent 5ff51bb commit 809a077
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 3 deletions.
33 changes: 33 additions & 0 deletions library/src/tests/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3009,6 +3009,39 @@ fn test_exp() {
.assert_eq(&dump);
}

#[test]
fn test_exp_mixed_paulis() {
let dump = test_expression(
indoc! {r#"
{
open Std.Math;
open Std.Diagnostics;
use qs = Qubit[3];
for q in qs {
H(q);
}
Exp([PauliX, PauliI, PauliY], PI() / 7.0, qs);
DumpMachine();
ResetAll(qs);
}
"#},
&Value::unit(),
);

expect![[r#"
STATE:
|000⟩: 0.4719+0.0000𝑖
|001⟩: 0.1651+0.0000𝑖
|010⟩: 0.4719+0.0000𝑖
|011⟩: 0.1651+0.0000𝑖
|100⟩: 0.4719+0.0000𝑖
|101⟩: 0.1651+0.0000𝑖
|110⟩: 0.4719+0.0000𝑖
|111⟩: 0.1651+0.0000𝑖
"#]]
.assert_eq(&dump);
}

#[test]
fn test_apply_unitary_with_h_matrix() {
let dump = test_expression(
Expand Down
6 changes: 3 additions & 3 deletions library/std/src/Std/Intrinsic.qs
Original file line number Diff line number Diff line change
Expand Up @@ -143,14 +143,14 @@ operation CNOT(control : Qubit, target : Qubit) : Unit is Adj + Ctl {
operation Exp(paulis : Pauli[], theta : Double, qubits : Qubit[]) : Unit is Adj + Ctl {
body ... {
Fact(Length(paulis) == Length(qubits), "Arrays 'pauli' and 'qubits' must have the same length");
let (newPaulis, newQubits) = RemovePauliI(paulis, qubits);
let (paulis, qubits) = RemovePauliI(paulis, qubits);
let angle = -2.0 * theta;
let len = Length(newPaulis);
let len = Length(paulis);

if len == 0 {
ApplyGlobalPhase(theta);
} elif len == 1 {
R(newPaulis[0], angle, qubits[0]);
R(paulis[0], angle, qubits[0]);
} elif len == 2 {
within {
MapPauli(qubits[1], paulis[0], paulis[1]);
Expand Down

0 comments on commit 809a077

Please sign in to comment.