These code samples were written by Mariia Mykhailova.
// Example 5-1: Integer increment-by-one operation (circuit implementation)
open Microsoft.Quantum.Diagnostics;
// Circuit implementation of modular increment operation
operation CircuitIncrement (register : Qubit[]) : Unit is Adj {
for i in Length(register) - 1 .. -1 .. 0 {
Controlled X(register[0 .. i - 1], register[i]);
}
}
operation CircuitIncrementAndDecrement () : Unit {
// allocate the qubit register
use register = Qubit[4];
// initialize the inputs
X(register[0]);
H(register[2]);
T(register[2]);
DumpMachine(());
// note that at this point non-zero amplitudes are at the basis states |1❭ and |5❭
Message("Increment (circuit implementation)");
CircuitIncrement(register);
DumpMachine(());
// note that after incrementing the same amplitudes shifted to the basis states |5❭ and |6❭
// decrement is an adjoint of increment, so we don't need to implement it separately
Message("Decrement (curcuit implementation)");
Adjoint CircuitIncrement(register);
DumpMachine(());
// make sure the qubits are back to the |0❭ state
ResetAll(register);
}
Note the use of %config
below: setting dump.truncateSmallAmplitudes
to true
hides the basis states of a state vector with near-zero measurement probabilities.
%config dump.truncateSmallAmplitudes=true
%simulate CircuitIncrementAndDecrement
Qubit IDs | 0, 1, 2, 3 | ||
---|---|---|---|
Basis state (little endian) | Amplitude | Meas. Pr. | Phase |
$\left|1\right\rangle$ | $0.7071 + 0.0000 i$ | ↑ | |
$\left|5\right\rangle$ | $0.5000 + 0.5000 i$ | ↑ |
Increment (circuit implementation)
Qubit IDs | 0, 1, 2, 3 | ||
---|---|---|---|
Basis state (little endian) | Amplitude | Meas. Pr. | Phase |
$\left|2\right\rangle$ | $0.7071 + 0.0000 i$ | ↑ | |
$\left|6\right\rangle$ | $0.5000 + 0.5000 i$ | ↑ |
Decrement (curcuit implementation)
Qubit IDs | 0, 1, 2, 3 | ||
---|---|---|---|
Basis state (little endian) | Amplitude | Meas. Pr. | Phase |
$\left|1\right\rangle$ | $0.7071 + 0.0000 i$ | ↑ | |
$\left|5\right\rangle$ | $0.5000 + 0.5000 i$ | ↑ |
()
// Example 5-1: Integer increment-by-one operation (using library operation)
open Microsoft.Quantum.Arithmetic;
open Microsoft.Quantum.Diagnostics;
operation LibraryIncrementAndDecrement () : Unit {
// allocate the qubit register
use register = Qubit[4];
// initialize the inputs
X(register[0]);
H(register[2]);
T(register[2]);
DumpMachine(());
// note that at this point non-zero amplitudes are at the basis states |1❭ and |5❭
// Increment the register using library implementation of the increment from Microsoft.Quantum.Arithmetic
Message("Increment (library implementation)");
IncrementByInteger(1, LittleEndian(register));
DumpMachine();
Message("Decrement (library implementation)");
IncrementByInteger(-1, LittleEndian(register));
DumpMachine();
// make sure the qubits are back to the |0❭ state
ResetAll(register);
}
%simulate LibraryIncrementAndDecrement
Qubit IDs | 0, 1, 2, 3 | ||
---|---|---|---|
Basis state (little endian) | Amplitude | Meas. Pr. | Phase |
$\left|1\right\rangle$ | $0.7071 + 0.0000 i$ | ↑ | |
$\left|5\right\rangle$ | $0.5000 + 0.5000 i$ | ↑ |
Increment (library implementation)
Qubit IDs | 0, 1, 2, 3 | ||
---|---|---|---|
Basis state (little endian) | Amplitude | Meas. Pr. | Phase |
$\left|2\right\rangle$ | $0.7071 -0.0000 i$ | ↑ | |
$\left|6\right\rangle$ | $0.5000 + 0.5000 i$ | ↑ |
Decrement (library implementation)
Qubit IDs | 0, 1, 2, 3 | ||
---|---|---|---|
Basis state (little endian) | Amplitude | Meas. Pr. | Phase |
$\left|1\right\rangle$ | $0.7071 + 0.0000 i$ | ↑ | |
$\left|5\right\rangle$ | $0.5000 + 0.5000 i$ | ↑ |
()
%package Microsoft.Quantum.Numerics
Adding package Microsoft.Quantum.Numerics: done!
// Example 5-2: Adding two quantum integers
open Microsoft.Quantum.Diagnostics;
// Open namespace which defines arithmetic operations
open Microsoft.Quantum.Arithmetic;
operation QuantumAddition () : Unit {
use (a, b) = (Qubit[4], Qubit[2]);
// Initialize the inputs
X(a[0]);
H(a[2]);
T(a[2]);
Message("Register a");
DumpRegister((), a);
// At this point non-zero amplitudes of register a are at the basis states |1❭ and |5❭
X(b[0]);
H(b[1]);
T(b[1]);
Message("Register b");
DumpRegister((), b);
// At this point non-zero amplitudes of register b are at the basis states |1❭ and |3❭
// The library operation AddI will add the first parameter to the second one
AddI(LittleEndian(b), LittleEndian(a));
// Note that now the registers a and b are entangled, so you can not look at just the state of the register b.
Message("State of the system after computing a += b");
DumpMachine();
// The output of this operation is a bit tricky to decipher, since it represents both registers a and b.
// Register a is the lowest 4 bits of the overall state, and register b is the highest 2 bits.
// Thus, the non-zero amplitude 0.5 of the basis state |18❭ corresponds to the little-endian bit mask 010010,
// which can be split up into registers a and b as 0100 10,
// which in turn is converted to decimal numbers 2 and 1:
// the first number is the basis state of register a, storing the sum of basis states |1❭ and |1❭,
// and the second number is the input state of register b (|1❭).
// The amplitude of this state is a product of the amplitudes of the basis states |1❭ and |1❭ that were added, 1/sqrt(2) * 1/sqrt(2).
// The rest of the states can be traced in a similar way.
// Make sure the qubits are back to the |0❭ state
ResetAll(a + b);
}
%simulate QuantumAddition
Register a
Qubit IDs | 0, 1, 2, 3 | ||
---|---|---|---|
Basis state (little endian) | Amplitude | Meas. Pr. | Phase |
$\left|1\right\rangle$ | $0.7071 + 0.0000 i$ | ↑ | |
$\left|5\right\rangle$ | $0.5000 + 0.5000 i$ | ↑ |
Register b
Qubit IDs | 4, 5 | ||
---|---|---|---|
Basis state (little endian) | Amplitude | Meas. Pr. | Phase |
$\left|1\right\rangle$ | $0.5000 + 0.5000 i$ | ↑ | |
$\left|3\right\rangle$ | $0.0000 + 0.7071 i$ | ↑ |
State of the system after computing a += b
Qubit IDs | 0, 1, 2, 3, 4, 5 | ||
---|---|---|---|
Basis state (little endian) | Amplitude | Meas. Pr. | Phase |
$\left|18\right\rangle$ | $0.5000 + 0.0000 i$ | ↑ | |
$\left|22\right\rangle$ | $0.3536 + 0.3536 i$ | ↑ | |
$\left|52\right\rangle$ | $0.3536 + 0.3536 i$ | ↑ | |
$\left|56\right\rangle$ | $0.0000 + 0.5000 i$ | ↑ |
()
// Example 5-3: Some interesting arithmetic
open Microsoft.Quantum.Diagnostics;
open Microsoft.Quantum.Arithmetic;
operation AddBSquared () : Unit {
use (a, b) = (Qubit[4], Qubit[2]);
// Initialize the inputs
X(a[0]);
H(a[2]);
T(a[2]);
Message("Register a");
DumpRegister((), a);
// At this point non-zero amplitudes of register a are at the basis states |1❭ and |5❭
X(b[0]);
H(b[1]);
T(b[1]);
Message("Register b");
DumpRegister((), b);
// At this point non-zero amplitudes of register b are at the basis states |1❭ and |3❭
// Allocate extra qubits to hold the value of b² temporarily;
// note that the register has to have twice the number of qubits in register b.
use anc = Qubit[4];
within {
// Compute anc = b * b
SquareI(LittleEndian(b), LittleEndian(anc));
} apply {
// Compute a += anc
AddI(LittleEndian(anc), LittleEndian(a));
}
// Note that now the registers a and b are entangled, so you can not look at just the state of the register b.
Message("State of the system after computing a += b * b");
DumpMachine();
// The output of this operation can be deciphered in a same way as the previous one:
// basis states |18❭ and |22❭ remain unchanged, since they correspond to the number 1 written in register b;
// basis state |58❭ corresponds to little-endian binary 010111, which represents b = 3 and a + b * b = 1 + 3² = 10,
// and basis state |62❭ is binary 011111, which is b = 3 and a + b * b = 5 + 3² = 14.
// Make sure the qubits are back to the |0❭ state
ResetAll(a + b);
}
%simulate AddBSquared
Register a
Qubit IDs | 0, 1, 2, 3 | ||
---|---|---|---|
Basis state (little endian) | Amplitude | Meas. Pr. | Phase |
$\left|1\right\rangle$ | $0.7071 + 0.0000 i$ | ↑ | |
$\left|5\right\rangle$ | $0.5000 + 0.5000 i$ | ↑ |
Register b
Qubit IDs | 4, 5 | ||
---|---|---|---|
Basis state (little endian) | Amplitude | Meas. Pr. | Phase |
$\left|1\right\rangle$ | $0.5000 + 0.5000 i$ | ↑ | |
$\left|3\right\rangle$ | $0.0000 + 0.7071 i$ | ↑ |
State of the system after computing a += b * b
Qubit IDs | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 | ||
---|---|---|---|
Basis state (little endian) | Amplitude | Meas. Pr. | Phase |
$\left|18\right\rangle$ | $0.5000 + 0.0000 i$ | ↑ | |
$\left|22\right\rangle$ | $0.3536 + 0.3536 i$ | ↑ | |
$\left|58\right\rangle$ | $0.3536 + 0.3536 i$ | ↑ | |
$\left|62\right\rangle$ | $0.0000 + 0.5000 i$ | ↑ |
()
// Example 5-4: Quantum-conditional execution
open Microsoft.Quantum.Diagnostics;
open Microsoft.Quantum.Arithmetic;
operation QuantumConditionalExecution () : Unit {
use (a, b) = (Qubit[3], Qubit[3]);
// Initialize the inputs
X(a[0]);
H(a[2]);
Message("Register a");
DumpRegister((), a);
// At this point non-zero amplitudes of register a are at the basis states |1❭ and |5❭
X(b[0]);
H(b[1]);
T(b[1]);
Message("Register b");
DumpRegister((), b);
// At this point non-zero amplitudes of register b are at the basis states |1❭ and |3❭
// a -= 3
IncrementByInteger(-3, LittleEndian(a));
// if (a < 0) then b++;
(Controlled IncrementByInteger)([a[2]], (1, LittleEndian(b)));
// a += 3
IncrementByInteger(3, LittleEndian(a));
// Note that now the registers a and b are entangled, so you can not look at just the state of the register b.
Message("State of the system after the computation");
DumpMachine();
// Make sure the qubits are back to the |0❭ state
ResetAll(a + b);
}
%simulate QuantumConditionalExecution
Register a
Qubit IDs | 0, 1, 2 | ||
---|---|---|---|
Basis state (little endian) | Amplitude | Meas. Pr. | Phase |
$\left|1\right\rangle$ | $0.7071 + 0.0000 i$ | ↑ | |
$\left|5\right\rangle$ | $0.7071 + 0.0000 i$ | ↑ |
Register b
Qubit IDs | 3, 4, 5 | ||
---|---|---|---|
Basis state (little endian) | Amplitude | Meas. Pr. | Phase |
$\left|1\right\rangle$ | $0.7071 + 0.0000 i$ | ↑ | |
$\left|3\right\rangle$ | $0.5000 + 0.5000 i$ | ↑ |
State of the system after the computation
Qubit IDs | 0, 1, 2, 3, 4, 5 | ||
---|---|---|---|
Basis state (little endian) | Amplitude | Meas. Pr. | Phase |
$\left|13\right\rangle$ | $0.5000 -0.0000 i$ | ↑ | |
$\left|17\right\rangle$ | $0.5000 -0.0000 i$ | ↑ | |
$\left|29\right\rangle$ | $0.3536 + 0.3536 i$ | ↑ | |
$\left|33\right\rangle$ | $0.3536 + 0.3536 i$ | ↑ |
()
// Example 5-5: Phase-encoding the result
open Microsoft.Quantum.Diagnostics;
open Microsoft.Quantum.Arithmetic;
operation PhaseEncoding () : Unit {
use (a, b) = (Qubit[3], Qubit[2]);
// Initialize the inputs
H(a[0]);
H(a[1]);
Message("Register a");
DumpRegister((), a);
// At this point non-zero amplitudes of register a are at the basis states |0❭, |1❭, |2❭, and |3❭
X(b[0]);
H(b[1]);
Message("Register b");
DumpRegister((), b);
// At this point non-zero amplitudes of register b are at the basis states |1❭ and |3❭
Message("Complete state of the system");
DumpMachine(());
// a -= 3
IncrementByInteger(-3, LittleEndian(a));
// if (a < 0) and b == 1 then flip the phase
(ControlledOnInt(1, Z))(b, a[2]);
// a += 3
IncrementByInteger(3, LittleEndian(a));
// Note that now the registers a and b are entangled, so you can not look at just the state of the register b.
Message("State of the system after the computation");
DumpMachine(());
// Make sure the qubits are back to the |0❭ state
ResetAll(a + b);
}
%simulate PhaseEncoding
Register a
Qubit IDs | 0, 1, 2 | ||
---|---|---|---|
Basis state (little endian) | Amplitude | Meas. Pr. | Phase |
$\left|0\right\rangle$ | $0.5000 + 0.0000 i$ | ↑ | |
$\left|1\right\rangle$ | $0.5000 + 0.0000 i$ | ↑ | |
$\left|2\right\rangle$ | $0.5000 + 0.0000 i$ | ↑ | |
$\left|3\right\rangle$ | $0.5000 + 0.0000 i$ | ↑ |
Register b
Qubit IDs | 3, 4 | ||
---|---|---|---|
Basis state (little endian) | Amplitude | Meas. Pr. | Phase |
$\left|1\right\rangle$ | $0.7071 + 0.0000 i$ | ↑ | |
$\left|3\right\rangle$ | $0.7071 + 0.0000 i$ | ↑ |
Complete state of the system
Qubit IDs | 0, 1, 2, 3, 4 | ||
---|---|---|---|
Basis state (little endian) | Amplitude | Meas. Pr. | Phase |
$\left|8\right\rangle$ | $0.3536 + 0.0000 i$ | ↑ | |
$\left|9\right\rangle$ | $0.3536 + 0.0000 i$ | ↑ | |
$\left|10\right\rangle$ | $0.3536 + 0.0000 i$ | ↑ | |
$\left|11\right\rangle$ | $0.3536 + 0.0000 i$ | ↑ | |
$\left|24\right\rangle$ | $0.3536 + 0.0000 i$ | ↑ | |
$\left|25\right\rangle$ | $0.3536 + 0.0000 i$ | ↑ | |
$\left|26\right\rangle$ | $0.3536 + 0.0000 i$ | ↑ | |
$\left|27\right\rangle$ | $0.3536 + 0.0000 i$ | ↑ |
State of the system after the computation
Qubit IDs | 0, 1, 2, 3, 4 | ||
---|---|---|---|
Basis state (little endian) | Amplitude | Meas. Pr. | Phase |
$\left|8\right\rangle$ | $-0.3536 + 0.0000 i$ | ↑ | |
$\left|9\right\rangle$ | $-0.3536 + 0.0000 i$ | ↑ | |
$\left|10\right\rangle$ | $-0.3536 + 0.0000 i$ | ↑ | |
$\left|11\right\rangle$ | $0.3536 -0.0000 i$ | ↑ | |
$\left|24\right\rangle$ | $0.3536 -0.0000 i$ | ↑ | |
$\left|25\right\rangle$ | $0.3536 -0.0000 i$ | ↑ | |
$\left|26\right\rangle$ | $0.3536 + 0.0000 i$ | ↑ | |
$\left|27\right\rangle$ | $0.3536 + 0.0000 i$ | ↑ |
()
// Example 5-6: Logic using CNOT gates
open Microsoft.Quantum.Diagnostics;
open Microsoft.Quantum.Measurement;
operation CNOTLogic () : Unit {
Message("c = ~c");
use (a, b, c) = (Qubit(), Qubit(), Qubit());
Message($"Input: c = {M(c)}");
X(c);
Message($"Output: c = {M(c)}");
Reset(c);
// ------------------------------------------------------
Message("");
Message("if (b) then c = ~c");
// initialize input
X(b);
Message($"Input: b = {M(b)}, c = {M(c)}");
CNOT(b, c);
Message($"Output: b = {M(b)}, c = {M(c)}");
ResetAll([b, c]);
// ------------------------------------------------------
Message("");
Message("if (a and b) then c = ~c");
// initialize input
X(a);
X(b);
Message($"Input: a = {M(a)}, b = {M(b)}, c = {M(c)}");
(Controlled X)([a, b], c);
Message($"Output: a = {M(a)}, b = {M(b)}, c = {M(c)}");
ResetAll([a, b, c]);
}
%simulate CNOTLogic
c = ~c Input: c = Zero Output: c = One if (b) then c = ~c Input: b = One, c = Zero Output: b = One, c = One if (a and b) then c = ~c Input: a = One, b = One, c = Zero Output: a = One, b = One, c = One
()