I'm playing around with Q#, which uses C# as a driver. I'd like to pass a Qubit object to the Q# code but it isn't working as expected.
C# Driver
using Microsoft.Quantum.Simulation.Core;
using Microsoft.Quantum.Simulation.Simulators;
namespace Quantum.QSharpApplication1 {
class Driver {
static void Main(string[] args) {
using (var sim = new QuantumSimulator()) {
var x = new Microsoft.Quantum.Simulation.Common.QubitManager(10);
Qubit q1 = x.Allocate();
Solve.Run(sim, q1, 1);
}
System.Console.WriteLine("Press any key to continue...");
System.Console.ReadKey();
}
}
}
Q#
namespace Quantum.QSharpApplication1
{
open Microsoft.Quantum.Primitive;
open Microsoft.Quantum.Canon;
operation Solve (q : Qubit, sign : Int) : ()
{
body
{
let qp = M(q);
if (qp != Zero)
{
X(q);
}
H(q);
}
}
}
When I run this, it runs without error until it reaches the System.Console.* lines at which point it throws the following exception in the Q# code
System.AccessViolationException
HResult=0x80004003
Message=Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
Source=<Cannot evaluate the exception source>
StackTrace:
<Cannot evaluate the exception stack trace>
The debugger associates this with the "let qp = M(q);" line in Q#.
Note this does happen in the Solve.Run call, the real code has multiple Solve calls and the output appear correct. It only appears to occur after the using QuantumSimulator scope is left. I recall reading that the Qubit must be reset to zero before it is released. I'm not sure if that is the problem here, but I don't see a way to do that in C#. Interesting I remove the Console lines, the program will run without error (timing?).
The QubitManager
instance you used to create the qubits is not a singleton (each Simulator
has its own QubitManager
), therefore the Simulator
is not aware of the Qubit
your trying to manipulate on the Q# code, thus the AccessViolationException
.
In general, creating Qubits on the driver is not supported; you can only allocate qubits using the allocate
and borrowing
statements inside Q#. The recommendation is to create an entry point in Q# to allocate the qubits which does the qubit allocation and call this from the driver, for example:
// MyOp.qs
operation EntryPoint() : ()
{
body
{
using (register = Qubit[2])
{
myOp(register);
}
}
}
// Driver.cs
EntryPoint.Run().Wait();
Finally, note that in your driver code you have this:
Solve.Run(sim, q1, 1);
The Run
method returns a tasks that executes asynchronously. You must typically add a Wait()
to make sure it finishes execution:
EntryPoint.Run(sim, 1).Wait();
If you do this you will notice that failure during the Run
, not the Console.WriteLine
.
User contributions licensed under CC BY-SA 3.0