-
Notifications
You must be signed in to change notification settings - Fork 92
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add custom operations sample (#1995)
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 <swernli@microsoft.com>
- Loading branch information
1 parent
85eef3f
commit adb3a79
Showing
6 changed files
with
175 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
{} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
27
samples/algorithms/MajoranaQubits/src/HardwareIntrinsics.qs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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]) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters