Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 86 additions & 0 deletions samples/algorithms/PhaseEstimation.qs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/// # Sample
/// Quantum Phase Estimation
///
/// # Description
/// This sample demonstrates how to use Quantum Phase Estimation (QPE) algorithm
/// to estimate the eigenvalue of a specific unitary operation.
/// QPE algorithm is performed by calling `ApplyQPE` library operation.
/// Run this sample and check the histogram of results.

import Std.Math.*;

/// # Summary
/// Estimate the the eigenvalue of a specific unitary U for its eigenvector |010⟩
/// using `ApplyQPE`. The result is returned as a complex polar value.
operation Main() : ComplexPolar {
// Allocate qubits to be used in phase estimation
use state = Qubit[3];

// Prepare U eigenvector |010⟩
X(state[1]);

// Estimate eigenvalue of U corresponding eigenvector |010⟩
let eigenvalue = EstimateEigenvalue(U, state, 6);

// Reset the state qubits
ResetAll(state);

// The eigenvalue represented as ComplexPolar should be (1.0, π/3.0)
// or approximately (1.0, 1.04719755).
eigenvalue
}

/// # Summary
/// Estimate the eigenvalue of a unitary operation `U` with certain `precision`
/// for a given eigenvector using Quantum Phase Estimation (QPE) algorithm.
operation EstimateEigenvalue(
U : Qubit[] => Unit is Adj + Ctl,
eigenstate : Qubit[],
precision : Int
) : ComplexPolar {
// Allocate qubits to be used in phase estimation
use phase = Qubit[precision];

// Estimate eigenvalue of Rz gate corresponding eigenvector |1⟩
ApplyQPE(ApplyOperationPowerCA(_, U, _), eigenstate, phase);

// Measure qubit register `phase` as a binary fraction
let phaseEstimation = MeasureBinaryFractionLE(phase);

// Reset the qubits
ResetAll(phase);

// Return one data point for histogram display
new ComplexPolar {
Magnitude = 1.0,
Argument = phaseEstimation * 2.0 * Std.Math.PI()
}
}

/// # Summary
/// Given a qubit register `qs` measure each qubit in the register
/// assume reults represent a binary fraction in little-endian order
/// and return the fraction as a `Double` value.
operation MeasureBinaryFractionLE(qs : Qubit[]) : Double {
mutable result = 0.0;
mutable power = 1.0;
for i in Length(qs)-1..-1..0 {
power /= 2.0;
if (MResetZ(qs[i]) == One) {
result += power;
}
}
return result;
}

// U is the unitary gate for which we want to perform phase estimation.
// This operation operates on three qubits and can be represented as an 8x8 matrix.
// As number of qubits gets larger, the matrix representation becomes impractical,
// and finding exact eigenvalues classicaly becomes computationally prohibitive.
// But representation as a quantum circuit can still be concise and efficient.
operation U(qs : Qubit[]) : Unit is Ctl + Adj {
// Using the Rzz gate with the angle of π/3
// The eigenvalue of this gate is exp(i * π/3) for |010⟩
Rzz(Std.Math.PI() / 3.0, qs[0], qs[1]);
Rzz(Std.Math.PI() / 3.0, qs[1], qs[2]);
}
2 changes: 2 additions & 0 deletions samples_test/src/tests/algorithms.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ pub const HIDDENSHIFT_EXPECT_DEBUG: Expect = expect![[r#"
[170, 512, 999]"#]];
pub const HIDDENSHIFTNISQ_EXPECT: Expect = expect!["[One, Zero, Zero, Zero, Zero, One]"];
pub const HIDDENSHIFTNISQ_EXPECT_DEBUG: Expect = expect!["[One, Zero, Zero, Zero, Zero, One]"];
pub const PHASEESTIMATION_EXPECT: Expect = expect![[r#"(1.0, 1.0799224746714913)"#]];
pub const PHASEESTIMATION_EXPECT_DEBUG: Expect = expect![[r#"(1.0, 1.0799224746714913)"#]];
pub const PHASEFLIPCODE_EXPECT: Expect = expect![[r#"
STATE:
|000⟩: 0.4743+0.0000𝑖
Expand Down
Loading