Page 37 - MSDN Magazine, September 2019
P. 37
Converting that to its matrix form yields:
using (qubit = Qubit()) {
Reset(qubit); }
The Reset function returns the Qubit to the |0〉 state.
When exiting the using block, a qubit must be in the |0〉 state. This is a runtime requirement, enforced by the quantum simula- tor. You can pass a Qubit to other operations and change its state and so forth, but if execution reaches the end of the using block without the Qubit being returned to the |0〉 state, an exception is raised. You can disable exceptions for non-reset qubits via the QuantumSimulator constructor.
You can also create multiple Qubit objects using the array expression Qubit[]:
using (qubits = Qubit[2]) {
// Do something with the qubits...
ResetAll(qubits); }
The qubits created with the array expression still need to be reset when you’re done. Use the built-in ResetAll function to reset multiple qubits. Be aware that simulated qubits use an exponential amount of memory. Each allocated qubit doubles the amount of RAM required. In my tests on a machine with 16GB of RAM, usage got to around 13GB for 26 qubits. Exceeding that, virtual memory kicks in. I was able to achieve 31 qubits; however, the memory usage ballooned to
53GB. Unsurprisingly, 32 qubits produced an interop exception.
Bending Q# to Your Will
The example project passes qubits around asynchronously among objectsthatrepresentAlice,BobandCharlie.Forthatreason,I needed to find a way to retain Qubit objects and to circumvent Q#’s requirement that a using block be used.
There’s a strong affinity between the Q# and C# tooling in Visual Studio. When you build a Q# project, the .qs files in that project are translated into C#. The Q# tooling outputs its generated C# files with a “.g.cs” file extension, placing them in the \obj\qsharp\src directory of the parent project.
When a Qubit object is allocated in Q#, it must be returned to the simulator. This is enforced syntactically.
I suspect this translation step might be replaced with direct com- pilation to IL or something else in the future, given the investment Microsoft is making in the Q# compiler. For the moment, however, I found it useful to explore the generated .cs files by peeking at how things work behind the scenes. I soon realized that it’s possible to leverage the Q# SDK assemblies from C# to achieve what I needed.
The QOperations class, in the downloadable sample code, directly calls the Q# APIs, which allows it to request a Qubit from the simulator without having to immediately release it. Instead
000
√2 01 0 01 ([] []) []
Alice then sends her qubit to Bob.
To decode the message, Bob begins by applying a CNOT gate to the qubits:
(|10〉 + |01〉) CNOT|Ψ〉 = CNOT √2
You can now take the matrix result from the previous step and multiply it by the CNOT matrix, remembering that the scalar multiplier is commutable:
=1 0+1 =1
10000000 =101001=11=1 1+0
√2 0 0 01 01 01 √2 01 √2 0
[ ][] [] ([][])
When you factor the resulting matrix, you get:
= |01〉 + |11〉 √2
Bob then applies a Hadamard gate to Alice’s qubit: |Ψ〉 = H|0〉U|1〉 + H|1〉U|1〉
√2 YoucansubstituteinthematrixrepresentationoftheHadamard
gate and qubits:
1111U0+1110U0 [ ][][] [ ][][]
√21-10 0√21-11 1
Dividing top and bottom by √2 , you eliminate the common
01
divisor, which leaves some matrix arithmetic to do:
= [1 1][1]U[0]+ [1 1][0]U[0] 1 -1 0 1 1 -1 1 1
= [1]U[0]+ [1]U[0] 1 1 -1 1
000
[][][] 1 -1 0
= 1 + 1 = 1 =|01〉 000
As you can see, the final result is the original message sent by Alice!
When Alice passed her qubit through the X gate, it affected the overall superposition of the two qubits. Bob was able to determine the change Alice made by unwinding the superposed state.
Allocating Qubits
When a Qubit object is allocated in Q#, it must be returned to the simulator. This is enforced syntactically. A using statement is required to allocate qubits.
To allocate a single Qubit, use the Qubit expression, as shown here:
msdnmagazine.com
September 2019 29