Skip to content

Commit

Permalink
Add custom operations sample (#1995)
Browse files Browse the repository at this point in the history
This PR adds a new language sample showing how to use custom
measurements and a more comprehensive sample showing how to use custom
operations (intrinsics and measurements).

---------

Co-authored-by: Stefan J. Wernli <[email protected]>
  • Loading branch information
orpuente-MS and swernli authored Nov 22, 2024
1 parent 85eef3f commit adb3a79
Show file tree
Hide file tree
Showing 6 changed files with 175 additions and 0 deletions.
1 change: 1 addition & 0 deletions samples/algorithms/MajoranaQubits/qsharp.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
88 changes: 88 additions & 0 deletions samples/algorithms/MajoranaQubits/src/GateSet.qs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/// A set of gates built upon the custom measurements
/// provided by the hardware provider.
///
/// Source:
/// [1] Surface code compilation via edge-disjoint paths
/// https://arxiv.org/pdf/2110.11493

/// Apply a CNOT gate to the given qubits.
/// Source: [1] Figure 3.
operation CNOT(control : Qubit, target : Qubit) : Unit {
// Prepare an ancilla qubit in the |+⟩ state.
use ancilla = Qubit();
PrepareX(ancilla);

let a = Mzz(control, ancilla);
let b = Mxx(ancilla, target);
let c = Mz(ancilla);
Reset(ancilla);

if b == One {
Z(control);
}

if a != c {
X(target);
}
}


/// Prepare a qubit in the |+⟩ state.
operation PrepareX(q : Qubit) : Unit {
if Mx(q) == One {
Z(q);
}
}

/// Prepare a qubit in the |0⟩ state.
operation PrepareZ(q : Qubit) : Unit {
if Mz(q) == One {
X(q);
}
}

/// Prepare a Bell Pair.
/// Source: [1] Figure 18a.
operation BellPair(q1 : Qubit, q2 : Qubit) : Unit {
// Collapse the qubits onto the Pauli-Z basis.
Mz(q1);
Mz(q2);

// If they are not aligned in the Pauli-X basis, phase flip one of them.
if Mxx(q1, q2) == One {
Z(q2);
}
}

/// Measure a Bell Pair.
/// Source: [1] Figure 18b.
/// Below is a map showing how the Bell states map to the Result pairs:
/// |𝚽⁺⟩ -> (Zero, Zero)
/// |𝚿⁺⟩ -> (Zero, One)
/// |𝚽⁻⟩ -> (One, Zero)
/// |𝚿⁻⟩ -> (One, One)
operation BellMeasurement(q1 : Qubit, q2 : Qubit) : (Result, Result) {
let z = Mzz(q1, q2);
let x = Mxx(q1, q2);
(x, z)
}

/// User friendly wrapper around the Mx hardware gate.
operation Mx(q : Qubit) : Result {
HardwareIntrinsics.__quantum__qis__mx__body(q)
}

/// User friendly wrapper around the Mz hardware gate.
operation Mz(q : Qubit) : Result {
HardwareIntrinsics.__quantum__qis__mz__body(q)
}

/// User friendly wrapper around the Mxx hardware gate.
operation Mxx(q1 : Qubit, q2 : Qubit) : Result {
HardwareIntrinsics.__quantum__qis__mxx__body(q1, q2)
}

/// User friendly wrapper around the Mzz hardware gate.
operation Mzz(q1 : Qubit, q2 : Qubit) : Result {
HardwareIntrinsics.__quantum__qis__mzz__body(q1, q2)
}
27 changes: 27 additions & 0 deletions samples/algorithms/MajoranaQubits/src/HardwareIntrinsics.qs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/// A set of custom measurements exposed from a hardware
/// provider using Majorana Qubits.

@Measurement()
@SimulatableIntrinsic()
operation __quantum__qis__mx__body(q : Qubit) : Result {
H(q);
M(q)
}

@Measurement()
@SimulatableIntrinsic()
operation __quantum__qis__mz__body(q : Qubit) : Result {
M(q)
}

@Measurement()
@SimulatableIntrinsic()
operation __quantum__qis__mxx__body(q1 : Qubit, q2 : Qubit) : Result {
Std.Intrinsic.Measure([PauliX, PauliX], [q1, q2])
}

@Measurement()
@SimulatableIntrinsic()
operation __quantum__qis__mzz__body(q1 : Qubit, q2 : Qubit) : Result {
Std.Intrinsic.Measure([PauliZ, PauliZ], [q1, q2])
}
30 changes: 30 additions & 0 deletions samples/algorithms/MajoranaQubits/src/Main.qs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/// # Sample
/// Majorana Qubits
///
/// # Description
/// In hardware providing majorana qubits, common quantum operations
/// are implemented using measurements and Pauli corrections. This
/// sample shows a hypotetical hardware provider exposing some custom
/// gates to Q# and a small library built on top of it.

/// Sample program using custom gates from a hardware provider.
operation Main() : (Result, Result) {
// Create a Bell Pair in the |𝚽⁺⟩ state.
use qs = Qubit[2];
GateSet.BellPair(qs[0], qs[1]);

// Applying X to any of the qubits will result in the |𝚿⁺⟩ Bell state.
// X(qs[0]); // Uncomment to try

// Applying Z to any of the qubits will result in the |𝚽⁻⟩ Bell state.
// Z(qs[0]); // Uncomment to try

// Applying X and Z to the pair will result in the |𝚿⁻⟩ Bell state.
// Note that they can be applied to the same Qubit.
// Z(qs[0]); // Uncomment to try
// X(qs[0]);

let res = GateSet.BellMeasurement(qs[0], qs[1]);
ResetAll(qs);
res
}
27 changes: 27 additions & 0 deletions samples/language/CustomMeasurements.qs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// # Sample
// Custom Operations
//
// # Description
// The @Measurement attribute in Q# allows you to define custom measurements
// that are lowered to QIR in the same way the `M` measurement in the standard
// library is lowered. That means an `"irreversible"` attribute is added to
// the callable declaration and the output results are moved to the paramaters
// and treated as result registers.
//
// # Who is this for?
// The target audience are library authors targeting specific hardware.

/// Try running the command `Q#: Get QIR for the current Q# program`
/// in VS-Code's Command Palette.
operation Main() : Result {
use q = Qubit();
H(q);
__quantum__qis__mx__body(q)
}

@Measurement()
@SimulatableIntrinsic()
operation __quantum__qis__mx__body(q : Qubit) : Result {
H(q);
M(q)
}
2 changes: 2 additions & 0 deletions samples_test/src/tests/language.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,8 @@ pub const COPYANDUPDATEOPERATOR_EXPECT_DEBUG: Expect = expect![[r#"
Updated array: [10, 11, 100, 13]
Updated array: [10, 100, 12, 200]
()"#]];
pub const CUSTOMMEASUREMENTS_EXPECT: Expect = expect!["Zero"];
pub const CUSTOMMEASUREMENTS_EXPECT_DEBUG: Expect = expect!["Zero"];
pub const DATATYPES_EXPECT: Expect = expect![[r#"
Binary BigInt: 42
Octal BigInt: 42
Expand Down

0 comments on commit adb3a79

Please sign in to comment.