microsoft / qsharp-runtime

Runtime components for Q#
https://docs.microsoft.com/quantum
MIT License
285 stars 93 forks source link

Consistent feedback when unreleased qubits are accessed #984

Open msoeken opened 2 years ago

msoeken commented 2 years ago

Please describe what you would like the feature to accomplish.
Qubits are deallocated when the scope of the corresponding use statement is closed. When dangling qubits are returned, various errors are observed in different simulators.

Describe the solution you'd like The program should not compile independent of what simulator is used.

Describe alternatives you've considered
N/A

Additional context

QDK version: 0.24.201332
macOS 12.3.1 (21E258)
Processor: 2.3 GHz Quad-Core Intel Core i7
Memory: 32 GB 3733 MHz LPDDR4X

Consider the following program:

namespace Project {
    open Microsoft.Quantum.Arithmetic;
    open Microsoft.Quantum.Diagnostics;
    open Microsoft.Quantum.Intrinsic;

    operation InitializeLittleEndian(numBits : Int) : LittleEndian {
        use register = Qubit[numBits];
        return LittleEndian(register);
    }

    @EntryPoint()
    operation RunProgram() : Unit {
        let value = InitializeLittleEndian(6);
        ApplyXorInPlace(42, value);
        EqualityFactI(MeasureInteger(value), 42, "Unexpected value");
        Message("Done.");
    }
}

Running with different simulators:

$ dotnet run -- -s QuantumSimulator
# throws SIGFPE

$ dotnet run -- -s SparseSimulator
Done.

$ dotnet run -- -s ToffoliSimulator
Unhandled exception. System.ArgumentException: Cannot use qubit 1. Qubit has already been released. (Parameter 'target')
 ---> Microsoft.Quantum.Intrinsic.X on ./D:\a\1\s\submodules\qsharp-runtime\src\Simulation\TargetDefinitions\Intrinsic\X.qs:line 0
   at Microsoft.Quantum.Canon.ApplyIfCA on ./D:\a\1\s\submodules\QuantumLibraries\Standard\src\Canon\Combinators\ApplyIf.qs:line 0
   at Microsoft.Quantum.Canon.ApplyToEachCA on ./D:\a\1\s\submodules\QuantumLibraries\Standard\src\Canon\Combinators\ApplyToEach.qs:line 0
   at Microsoft.Quantum.Arithmetic.ApplyXorInPlace on ./D:\a\1\s\submodules\QuantumLibraries\Standard\src\Arithmetic\Arithmetic.qs:line 0
   at Project.RunProgram on ./Program.qs:line 0

Unhandled exception: System.ArgumentException: Cannot use qubit 1. Qubit has already been released. (Parameter 'target')
   at Microsoft.Quantum.Simulation.Common.SimulatorBase.CheckQubit(Qubit q, String qubitName)
   at Microsoft.Quantum.Simulation.Simulators.ToffoliSimulator.Microsoft.Quantum.Intrinsic.Interfaces.IIntrinsicX.Body(Qubit target)
   at Microsoft.Quantum.Intrinsic.X.<get___Body__>b__9_0(Qubit __in__)
   at Microsoft.Quantum.Simulation.Core.Operation`2.Apply(I a)
   at Microsoft.Quantum.Simulation.Core.Operation`2.Microsoft.Quantum.Simulation.Core.ICallable.Apply(Object args)
   at Microsoft.Quantum.Canon.ApplyIfCA`1.<>c.<get___Body__>b__7_0(ValueTuple`3 __in__)
   at Microsoft.Quantum.Simulation.Core.OperationPartial`3.<get___Body__>b__22_0(P a)
   at Microsoft.Quantum.Simulation.Core.Operation`2.Apply(I a)
   at Microsoft.Quantum.Simulation.Core.Operation`2.Apply[GenO](Object args)
   at Microsoft.Quantum.Simulation.Core.GenericCallable.Apply[O](Object args)
   at Microsoft.Quantum.Simulation.Core.GenericCallable.Microsoft.Quantum.Simulation.Core.ICallable.Apply(Object args)
   at Microsoft.Quantum.Canon.ApplyToEachCA`1.<get___Body__>b__16_0(ValueTuple`2 __in__)
   at Microsoft.Quantum.Simulation.Core.Operation`2.Apply(I a)
   at Microsoft.Quantum.Simulation.Core.Operation`2.Apply[GenO](Object args)
   at Microsoft.Quantum.Simulation.Core.GenericCallable.Apply[O](Object args)
   at Microsoft.Quantum.Simulation.Core.GenericCallable.Microsoft.Quantum.Simulation.Core.ICallable.Apply(Object args)
   at Microsoft.Quantum.Arithmetic.ApplyXorInPlace.<get___Body__>b__31_0(ValueTuple`2 __in__)
   at Microsoft.Quantum.Simulation.Core.Operation`2.Apply(I a)
   at Microsoft.Quantum.Simulation.Core.Operation`2.Microsoft.Quantum.Simulation.Core.ICallable<I,O>.Apply(I args)
   at Project.RunProgram.<get___Body__>b__28_0(QVoid __in__) in ./Program.qs:line 14
   at Microsoft.Quantum.Simulation.Core.Operation`2.Apply(I a)
   at Microsoft.Quantum.Simulation.Core.Operation`2.Apply[GenO](Object args)
   at Microsoft.Quantum.Simulation.Common.SimulatorBase.Execute[T,I,O](I args)
   at Microsoft.Quantum.Simulation.Common.SimulatorBase.<>c__DisplayClass68_0`3.<Run>b__0()
   at System.Threading.Tasks.Task`1.InnerInvoke()
   at System.Threading.Tasks.Task.<>c.<.cctor>b__272_0(Object obj)
   at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location ---
   at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread)
--- End of stack trace from previous location ---
   at Microsoft.Quantum.EntryPointDriver.Simulation`3.RunSimulator(TIn input, Func`1 createSimulator)
   at Microsoft.Quantum.EntryPointDriver.Simulation`3.Simulate(IEntryPoint entryPoint, TIn input, DriverSettings settings, String simulator)
   at System.CommandLine.Invocation.CommandHandler.GetResultCodeAsync(Object value, InvocationContext context)
   at System.CommandLine.Invocation.ModelBindingCommandHandler.InvokeAsync(InvocationContext context)
   at System.CommandLine.Invocation.InvocationPipeline.<>c__DisplayClass4_0.<<BuildInvocationChain>b__0>d.MoveNext()
--- End of stack trace from previous location ---
   at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c.<<UseParseErrorReporting>b__20_0>d.MoveNext()
--- End of stack trace from previous location ---
   at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c__DisplayClass15_0.<<UseHelp>b__0>d.MoveNext()
--- End of stack trace from previous location ---
   at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c__DisplayClass24_0.<<UseVersionOption>b__0>d.MoveNext()
--- End of stack trace from previous location ---
   at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c__DisplayClass22_0.<<UseTypoCorrections>b__0>d.MoveNext()
--- End of stack trace from previous location ---
   at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c.<<UseSuggestDirective>b__21_0>d.MoveNext()
--- End of stack trace from previous location ---
   at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c.<<UseParseDirective>b__19_0>d.MoveNext()
--- End of stack trace from previous location ---
   at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c.<<UseDebugDirective>b__11_0>d.MoveNext()
--- End of stack trace from previous location ---
   at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c.<<RegisterWithDotnetSuggest>b__10_0>d.MoveNext()
--- End of stack trace from previous location ---
   at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c__DisplayClass13_0.<<UseExceptionHandler>b__0>d.MoveNext()
bettinaheim commented 2 years ago

Options for a language update to have better compile time enforcement has been discussed, and I suggest engaging there. Solving this in the runtime is a bit suboptimal, and the ideal solution that you would like would indeed be preferable. That requires extensive work to support that, though.