These code samples were written by Mariia Mykhailova.
// Example 10-1: Encoding "(a OR NOT b) AND c" example in phase logic
open Microsoft.Quantum.Diagnostics;
operation RunExample101 () : Unit {
// Allocate the qubits a, b and c and a qubit for storing the result
use (a, b, c, scratch) = (Qubit(), Qubit(), Qubit(), Qubit());
// Prepare the "input" - a superposition of all states
ApplyToEach(H, [a, b, c]);
within {
// Compute (a OR NOT b) and write the result into "scratch" using magnitude-based encoding
// (within-apply construct will make sure that "within" block is uncomputed after "apply" block is done)
// Convert b to NOT b
X(b);
// Compute OR of a and updated b
ControlledOnInt(0, X)([a, b], scratch);
X(scratch);
} apply {
// Compute the last AND using phase-based encoding
Controlled Z([c], scratch);
}
// Dump the state of qubits a, b and c (scratch qubit is not entangled with them any longer).
// Note the negative phases of states |4❭, |5❭ and |7❭
DumpRegister((), [a, b, c]);
// Make sure the qubits are back to the |0❭ state
ResetAll([a, b, c, scratch]);
}
%simulate RunExample101
Qubit IDs | 0, 1, 2 | ||
---|---|---|---|
Basis state (little endian) | Amplitude | Meas. Pr. | Phase |
$\left|0\right\rangle$ | $0.3536 + 0.0000 i$ | ↑ | |
$\left|1\right\rangle$ | $0.3536 + 0.0000 i$ | ↑ | |
$\left|2\right\rangle$ | $0.3536 + 0.0000 i$ | ↑ | |
$\left|3\right\rangle$ | $0.3536 + 0.0000 i$ | ↑ | |
$\left|4\right\rangle$ | $-0.3536 + 0.0000 i$ | ↑ | |
$\left|5\right\rangle$ | $-0.3536 + 0.0000 i$ | ↑ | |
$\left|6\right\rangle$ | $0.3536 + 0.0000 i$ | ↑ | |
$\left|7\right\rangle$ | $-0.3536 + 0.0000 i$ | ↑ |
()
// Example 10-2: Kittens and tigers
open Microsoft.Quantum.Arrays;
open Microsoft.Quantum.Diagnostics;
open Microsoft.Quantum.Measurement;
operation MirrorRegister (register : Qubit[]) : Unit {
within {
ApplyToEachA(H, register);
ApplyToEachA(X, register);
} apply {
Controlled Z(Most(register), Tail(register));
}
}
operation KittensAndTigers () : Unit {
// Allocate the qubits
use (boxes, noteA, scratch) = (Qubit[2], Qubit(), Qubit());
// Prepare the boxes in a superposition of all states
ApplyToEach(H, boxes);
within {
// Compute note A ("at least one of these boxes contains a kitten" = boxA or boxB)
(ControlledOnInt(0, X))(boxes, noteA);
X(noteA);
// Compute note B ("boxA contains a tiger")
X(boxes[0]);
// Put phase-encoded scratch qubit in |-❭ state
X(scratch);
H(scratch);
} apply {
// Compute the last XNOR
CNOT(boxes[0], scratch);
CNOT(noteA, scratch);
X(scratch);
}
// Dump the state of qubits "boxes" (two other qubits are not entangled with them any longer).
// At this point the answer is phase-encoded.
Message("Computation result encoded in phases");
DumpRegister((), boxes);
// Convert the phase encoding into magnitudes encoding
MirrorRegister(boxes);
// Dump the state of qubits "boxes" again.
// At this point the answer is magnitudes-encoded.
Message("Computation result encoded in amplitudes");
DumpRegister((), boxes);
// Perform measurements to extract the result
let catA = MResetZ(boxes[0]) == One ? "kitten" | "tiger";
let catB = MResetZ(boxes[1]) == One ? "kitten" | "tiger";
Message($"Box A contains {catA}");
Message($"Box B contains {catB}");
}
%simulate KittensAndTigers
Computation result encoded in phases
Qubit IDs | 0, 1 | ||
---|---|---|---|
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$ | ↑ |
Computation result encoded in amplitudes
Qubit IDs | 0, 1 | ||
---|---|---|---|
Basis state (little endian) | Amplitude | Meas. Pr. | Phase |
$\left|0\right\rangle$ | $-0.0000 + 0.0000 i$ | ↑ | |
$\left|1\right\rangle$ | $-0.0000 + 0.0000 i$ | ↑ | |
$\left|2\right\rangle$ | $-1.0000 + 0.0000 i$ | ↑ | |
$\left|3\right\rangle$ | $0.0000 + 0.0000 i$ | ↑ |
Box A contains tiger Box B contains kitten
()
(a OR b) AND (NOT a OR c) AND (NOT b OR NOT c) AND (a OR c)
// Example 10-3: Satisfiable 3-SAT problem
open Microsoft.Quantum.Arrays;
open Microsoft.Quantum.Convert;
open Microsoft.Quantum.Diagnostics;
open Microsoft.Quantum.Measurement;
// Helper operation to compute OR of several inputs and write it to the output
// negate[i] = true if variable i is included in the clause negated
operation ComputeOrClause (inputs : Qubit[], negate : Bool[], output : Qubit) : Unit is Adj {
within {
// Flip the inputs that have to be negated, so as to calculate a normal OR of inputs
ApplyPauliFromBitString(PauliX, true, negate, inputs);
} apply {
(ControlledOnInt(0, X))(inputs, output);
X(output);
}
}
operation SolveSatisfiableSAT () : Unit {
// Allocate the qubits
use (inputs, clauses) = (Qubit[3], Qubit[4]);
// Prepare the inputs in a superposition of all states
ApplyToEach(H, inputs);
within {
// Clause 1: a OR b = inputs[0] OR inputs[1]
ComputeOrClause(inputs[0..1], [false, false], clauses[0]);
// Clause 2: NOT a OR c = NOT inputs[0] OR inputs[2]
ComputeOrClause(inputs[0..2..2], [true, false], clauses[1]);
// Clause 3: NOT b OR NOT c = NOT inputs[1] OR NOT inputs[2]
ComputeOrClause(inputs[1..2], [true, true], clauses[2]);
// Clause 4: a OR c = inputs[0] OR inputs[2]
ComputeOrClause(inputs[0..2..2], [false, false], clauses[3]);
} apply {
// Compute the (phase-encoded) result
Controlled Z(Most(clauses), Tail(clauses));
}
// Dump the state of inputs (the clauses are not entangled with them any longer).
// At this point the answer is phase-encoded.
Message("Computation result encoded in phases");
DumpRegister((), inputs);
// Convert the phase encoding into magnitudes encoding
MirrorRegister(inputs);
// Dump the state of qubits "boxes" again.
// At this point the answer is magnitudes-encoded.
Message("Computation result encoded in amplitudes");
DumpRegister((), inputs);
// Perform measurements to extract the result
let solution = ResultArrayAsBoolArray(MultiM(inputs));
Message($"Variables [a, b, c] = {solution}");
ResetAll(inputs);
}
%simulate SolveSatisfiableSAT
Computation result encoded in phases
Qubit IDs | 0, 1, 2 | ||
---|---|---|---|
Basis state (little endian) | Amplitude | Meas. Pr. | Phase |
$\left|0\right\rangle$ | $0.3536 + 0.0000 i$ | ↑ | |
$\left|1\right\rangle$ | $0.3536 + 0.0000 i$ | ↑ | |
$\left|2\right\rangle$ | $0.3536 + 0.0000 i$ | ↑ | |
$\left|3\right\rangle$ | $0.3536 + 0.0000 i$ | ↑ | |
$\left|4\right\rangle$ | $0.3536 + 0.0000 i$ | ↑ | |
$\left|5\right\rangle$ | $-0.3536 + 0.0000 i$ | ↑ | |
$\left|6\right\rangle$ | $0.3536 + 0.0000 i$ | ↑ | |
$\left|7\right\rangle$ | $0.3536 + 0.0000 i$ | ↑ |
Computation result encoded in amplitudes
Qubit IDs | 0, 1, 2 | ||
---|---|---|---|
Basis state (little endian) | Amplitude | Meas. Pr. | Phase |
$\left|0\right\rangle$ | $-0.1768 + 0.0000 i$ | ↑ | |
$\left|1\right\rangle$ | $-0.1768 + 0.0000 i$ | ↑ | |
$\left|2\right\rangle$ | $-0.1768 + 0.0000 i$ | ↑ | |
$\left|3\right\rangle$ | $-0.1768 + 0.0000 i$ | ↑ | |
$\left|4\right\rangle$ | $-0.1768 + 0.0000 i$ | ↑ | |
$\left|5\right\rangle$ | $-0.8839 + 0.0000 i$ | ↑ | |
$\left|6\right\rangle$ | $-0.1768 + 0.0000 i$ | ↑ | |
$\left|7\right\rangle$ | $-0.1768 + 0.0000 i$ | ↑ |
Variables [a, b, c] = [True,False,True]
()
(a OR b) AND (NOT a OR c) AND (NOT b OR NOT c) AND (a OR c) AND B
// Example 10-4: Unsatisfiable 3-SAT problem
open Microsoft.Quantum.Arrays;
open Microsoft.Quantum.Convert;
open Microsoft.Quantum.Diagnostics;
open Microsoft.Quantum.Measurement;
operation SolveUnsatisfiableSAT () : Unit {
// Allocate the qubits
use (inputs, clauses) = (Qubit[3], Qubit[4]);
// Prepare the inputs in a superposition of all states
ApplyToEach(H, inputs);
within {
// Clause 1: a OR b = inputs[0] OR inputs[1]
ComputeOrClause(inputs[0..1], [false, false], clauses[0]);
// Clause 2: NOT a OR c = NOT inputs[0] OR inputs[2]
ComputeOrClause(inputs[0..2..2], [true, false], clauses[1]);
// Clause 3: NOT b OR NOT c = NOT inputs[1] OR NOT inputs[2]
ComputeOrClause(inputs[1..2], [true, true], clauses[2]);
// Clause 4: a OR c = inputs[0] OR inputs[2]
ComputeOrClause(inputs[0..2..2], [false, false], clauses[3]);
// New clause 5 is b itself, so doesn't need an extra input to be computed
} apply {
// Compute the (phase-encoded) result
Controlled Z(clauses, inputs[1]);
}
// Dump the state of inputs (the clauses are not entangled with them any longer).
// At this point the answer is phase-encoded.
Message("Computation result encoded in phases");
DumpRegister((), inputs);
// Convert the phase encoding into magnitudes encoding
MirrorRegister(inputs);
// Dump the state of qubits "boxes" again.
// At this point the answer is magnitudes-encoded.
Message("Computation result encoded in amplitudes");
DumpRegister((), inputs);
// Perform measurements to extract the result
let solution = ResultArrayAsBoolArray(MultiM(inputs));
Message($"Variables [a, b, c] = {solution}");
ResetAll(inputs);
}
Run the cell below several times - you'll see different results!
%simulate SolveUnsatisfiableSAT
Computation result encoded in phases
Qubit IDs | 0, 1, 2 | ||
---|---|---|---|
Basis state (little endian) | Amplitude | Meas. Pr. | Phase |
$\left|0\right\rangle$ | $0.3536 + 0.0000 i$ | ↑ | |
$\left|1\right\rangle$ | $0.3536 + 0.0000 i$ | ↑ | |
$\left|2\right\rangle$ | $0.3536 + 0.0000 i$ | ↑ | |
$\left|3\right\rangle$ | $0.3536 + 0.0000 i$ | ↑ | |
$\left|4\right\rangle$ | $0.3536 + 0.0000 i$ | ↑ | |
$\left|5\right\rangle$ | $0.3536 + 0.0000 i$ | ↑ | |
$\left|6\right\rangle$ | $0.3536 + 0.0000 i$ | ↑ | |
$\left|7\right\rangle$ | $0.3536 + 0.0000 i$ | ↑ |
Computation result encoded in amplitudes
Qubit IDs | 0, 1, 2 | ||
---|---|---|---|
Basis state (little endian) | Amplitude | Meas. Pr. | Phase |
$\left|0\right\rangle$ | $-0.3536 + 0.0000 i$ | ↑ | |
$\left|1\right\rangle$ | $-0.3536 + 0.0000 i$ | ↑ | |
$\left|2\right\rangle$ | $-0.3536 + 0.0000 i$ | ↑ | |
$\left|3\right\rangle$ | $-0.3536 + 0.0000 i$ | ↑ | |
$\left|4\right\rangle$ | $-0.3536 + 0.0000 i$ | ↑ | |
$\left|5\right\rangle$ | $-0.3536 + 0.0000 i$ | ↑ | |
$\left|6\right\rangle$ | $-0.3536 + 0.0000 i$ | ↑ | |
$\left|7\right\rangle$ | $-0.3536 + 0.0000 i$ | ↑ |
Variables [a, b, c] = [False,False,False]
()