Skip to content

Commit adb3a79

Browse files
orpuente-MSswernli
andauthored
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 <[email protected]>
1 parent 85eef3f commit adb3a79

File tree

6 files changed

+175
-0
lines changed

6 files changed

+175
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/// A set of gates built upon the custom measurements
2+
/// provided by the hardware provider.
3+
///
4+
/// Source:
5+
/// [1] Surface code compilation via edge-disjoint paths
6+
/// https://arxiv.org/pdf/2110.11493
7+
8+
/// Apply a CNOT gate to the given qubits.
9+
/// Source: [1] Figure 3.
10+
operation CNOT(control : Qubit, target : Qubit) : Unit {
11+
// Prepare an ancilla qubit in the |+⟩ state.
12+
use ancilla = Qubit();
13+
PrepareX(ancilla);
14+
15+
let a = Mzz(control, ancilla);
16+
let b = Mxx(ancilla, target);
17+
let c = Mz(ancilla);
18+
Reset(ancilla);
19+
20+
if b == One {
21+
Z(control);
22+
}
23+
24+
if a != c {
25+
X(target);
26+
}
27+
}
28+
29+
30+
/// Prepare a qubit in the |+⟩ state.
31+
operation PrepareX(q : Qubit) : Unit {
32+
if Mx(q) == One {
33+
Z(q);
34+
}
35+
}
36+
37+
/// Prepare a qubit in the |0⟩ state.
38+
operation PrepareZ(q : Qubit) : Unit {
39+
if Mz(q) == One {
40+
X(q);
41+
}
42+
}
43+
44+
/// Prepare a Bell Pair.
45+
/// Source: [1] Figure 18a.
46+
operation BellPair(q1 : Qubit, q2 : Qubit) : Unit {
47+
// Collapse the qubits onto the Pauli-Z basis.
48+
Mz(q1);
49+
Mz(q2);
50+
51+
// If they are not aligned in the Pauli-X basis, phase flip one of them.
52+
if Mxx(q1, q2) == One {
53+
Z(q2);
54+
}
55+
}
56+
57+
/// Measure a Bell Pair.
58+
/// Source: [1] Figure 18b.
59+
/// Below is a map showing how the Bell states map to the Result pairs:
60+
/// |𝚽⁺⟩ -> (Zero, Zero)
61+
/// |𝚿⁺⟩ -> (Zero, One)
62+
/// |𝚽⁻⟩ -> (One, Zero)
63+
/// |𝚿⁻⟩ -> (One, One)
64+
operation BellMeasurement(q1 : Qubit, q2 : Qubit) : (Result, Result) {
65+
let z = Mzz(q1, q2);
66+
let x = Mxx(q1, q2);
67+
(x, z)
68+
}
69+
70+
/// User friendly wrapper around the Mx hardware gate.
71+
operation Mx(q : Qubit) : Result {
72+
HardwareIntrinsics.__quantum__qis__mx__body(q)
73+
}
74+
75+
/// User friendly wrapper around the Mz hardware gate.
76+
operation Mz(q : Qubit) : Result {
77+
HardwareIntrinsics.__quantum__qis__mz__body(q)
78+
}
79+
80+
/// User friendly wrapper around the Mxx hardware gate.
81+
operation Mxx(q1 : Qubit, q2 : Qubit) : Result {
82+
HardwareIntrinsics.__quantum__qis__mxx__body(q1, q2)
83+
}
84+
85+
/// User friendly wrapper around the Mzz hardware gate.
86+
operation Mzz(q1 : Qubit, q2 : Qubit) : Result {
87+
HardwareIntrinsics.__quantum__qis__mzz__body(q1, q2)
88+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/// A set of custom measurements exposed from a hardware
2+
/// provider using Majorana Qubits.
3+
4+
@Measurement()
5+
@SimulatableIntrinsic()
6+
operation __quantum__qis__mx__body(q : Qubit) : Result {
7+
H(q);
8+
M(q)
9+
}
10+
11+
@Measurement()
12+
@SimulatableIntrinsic()
13+
operation __quantum__qis__mz__body(q : Qubit) : Result {
14+
M(q)
15+
}
16+
17+
@Measurement()
18+
@SimulatableIntrinsic()
19+
operation __quantum__qis__mxx__body(q1 : Qubit, q2 : Qubit) : Result {
20+
Std.Intrinsic.Measure([PauliX, PauliX], [q1, q2])
21+
}
22+
23+
@Measurement()
24+
@SimulatableIntrinsic()
25+
operation __quantum__qis__mzz__body(q1 : Qubit, q2 : Qubit) : Result {
26+
Std.Intrinsic.Measure([PauliZ, PauliZ], [q1, q2])
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/// # Sample
2+
/// Majorana Qubits
3+
///
4+
/// # Description
5+
/// In hardware providing majorana qubits, common quantum operations
6+
/// are implemented using measurements and Pauli corrections. This
7+
/// sample shows a hypotetical hardware provider exposing some custom
8+
/// gates to Q# and a small library built on top of it.
9+
10+
/// Sample program using custom gates from a hardware provider.
11+
operation Main() : (Result, Result) {
12+
// Create a Bell Pair in the |𝚽⁺⟩ state.
13+
use qs = Qubit[2];
14+
GateSet.BellPair(qs[0], qs[1]);
15+
16+
// Applying X to any of the qubits will result in the |𝚿⁺⟩ Bell state.
17+
// X(qs[0]); // Uncomment to try
18+
19+
// Applying Z to any of the qubits will result in the |𝚽⁻⟩ Bell state.
20+
// Z(qs[0]); // Uncomment to try
21+
22+
// Applying X and Z to the pair will result in the |𝚿⁻⟩ Bell state.
23+
// Note that they can be applied to the same Qubit.
24+
// Z(qs[0]); // Uncomment to try
25+
// X(qs[0]);
26+
27+
let res = GateSet.BellMeasurement(qs[0], qs[1]);
28+
ResetAll(qs);
29+
res
30+
}
+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// # Sample
2+
// Custom Operations
3+
//
4+
// # Description
5+
// The @Measurement attribute in Q# allows you to define custom measurements
6+
// that are lowered to QIR in the same way the `M` measurement in the standard
7+
// library is lowered. That means an `"irreversible"` attribute is added to
8+
// the callable declaration and the output results are moved to the paramaters
9+
// and treated as result registers.
10+
//
11+
// # Who is this for?
12+
// The target audience are library authors targeting specific hardware.
13+
14+
/// Try running the command `Q#: Get QIR for the current Q# program`
15+
/// in VS-Code's Command Palette.
16+
operation Main() : Result {
17+
use q = Qubit();
18+
H(q);
19+
__quantum__qis__mx__body(q)
20+
}
21+
22+
@Measurement()
23+
@SimulatableIntrinsic()
24+
operation __quantum__qis__mx__body(q : Qubit) : Result {
25+
H(q);
26+
M(q)
27+
}

samples_test/src/tests/language.rs

+2
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,8 @@ pub const COPYANDUPDATEOPERATOR_EXPECT_DEBUG: Expect = expect![[r#"
144144
Updated array: [10, 11, 100, 13]
145145
Updated array: [10, 100, 12, 200]
146146
()"#]];
147+
pub const CUSTOMMEASUREMENTS_EXPECT: Expect = expect!["Zero"];
148+
pub const CUSTOMMEASUREMENTS_EXPECT_DEBUG: Expect = expect!["Zero"];
147149
pub const DATATYPES_EXPECT: Expect = expect![[r#"
148150
Binary BigInt: 42
149151
Octal BigInt: 42

0 commit comments

Comments
 (0)