예제 #1
0
        /// <summary>
        ///     Simulates an operation given a string with its name and a JSON
        ///     encoding of its arguments.
        /// </summary>
        public async Task <ExecutionResult> RunAsync(string input, IChannel channel)
        {
            var inputParameters = ParseInputParameters(input, firstParameterInferredName: ParameterNameOperationName);

            var name   = inputParameters.DecodeParameter <string>(ParameterNameOperationName);
            var symbol = SymbolResolver.Resolve(name) as IQSharpSymbol;

            if (symbol == null)
            {
                throw new InvalidOperationException($"Invalid operation name: {name}");
            }

            var maxNQubits = 0L;

            using var qsim = new QuantumSimulator()
                             .WithJupyterDisplay(channel, ConfigurationSource)
                             .WithStackTraceDisplay(channel);
            qsim.OnDisplayableDiagnostic += channel.Display;
            qsim.AfterAllocateQubits     += (args) =>
            {
                maxNQubits = System.Math.Max(qsim.QubitManager.AllocatedQubitsCount, maxNQubits);
            };
            var stopwatch = Stopwatch.StartNew();
            var value     = await symbol.Operation.RunAsync(qsim, inputParameters);

            stopwatch.Stop();
            var result = value.ToExecutionResult();

            (Monitor as PerformanceMonitor)?.ReportSimulatorPerformance(new SimulatorPerformanceArgs(
                                                                            simulatorName: qsim.GetType().FullName,
                                                                            nQubits: (int)maxNQubits,
                                                                            duration: stopwatch.Elapsed
                                                                            ));
            return(result);
        }
예제 #2
0
        /// <summary>
        ///     Outputs a visualization of a runtime execution path of an operation given
        ///     a string with its name and a JSON encoding of its arguments.
        /// </summary>
        public async Task <ExecutionResult> RunAsync(string input, IChannel channel)
        {
            // Parse input parameters
            var inputParameters = ParseInputParameters(input, firstParameterInferredName: ParameterNameOperationName);

            var name   = inputParameters.DecodeParameter <string>(ParameterNameOperationName);
            var symbol = SymbolResolver.Resolve(name) as IQSharpSymbol;

            if (symbol == null)
            {
                throw new InvalidOperationException($"Invalid operation name: {name}");
            }

            if (!inputParameters.TryDecodeParameter <int>(
                    ParameterNameDepth,
                    out var depth,
                    defaultValue: this.ConfigurationSource.TraceVisualizationDefaultDepth
                    ))
            {
                channel.Stderr($"Expected {ParameterNameDepth} to be an integer, but got {inputParameters[ParameterNameDepth]}.");
                return(ExecuteStatus.Error.ToExecutionResult());
            }

            if (depth <= 0)
            {
                channel.Stderr($"Expected {ParameterNameDepth} to be >= 1, but got {depth}.");
                return(ExecuteStatus.Error.ToExecutionResult());
            }

            var tracer = new ExecutionPathTracer.ExecutionPathTracer();

            // Simulate operation and attach `ExecutionPathTracer` to trace out operations performed
            // in its execution path
            using var qsim = new QuantumSimulator()
                             .WithExecutionPathTracer(tracer);
            var value = await symbol.Operation.RunAsync(qsim, inputParameters);

            var divId = $"execution-path-container-{Guid.NewGuid()}";

            channel.DisplayUpdatable(new DisplayableHtmlElement($"<div id='{divId}' />"));

            // Render the `ExecutionPath` traced out by the `ExecutionPathTracer`
            tracer.RenderExecutionPath(channel, divId, depth, this.ConfigurationSource.TraceVisualizationStyle);

            return(ExecuteStatus.Ok.ToExecutionResult());
        }
예제 #3
0
        /// <summary>
        ///     Simulates an operation given a string with its name and a JSON
        ///     encoding of its arguments.
        /// </summary>
        public async Task <ExecutionResult> RunAsync(string input, IChannel channel)
        {
            var(name, args) = ParseInput(input);

            var symbol = SymbolResolver.Resolve(name) as IQSharpSymbol;

            if (symbol == null)
            {
                throw new InvalidOperationException($"Invalid operation name: {name}");
            }

            using var qsim = new QuantumSimulator()
                             .WithJupyterDisplay(channel, ConfigurationSource)
                             .WithStackTraceDisplay(channel);
            var value = await symbol.Operation.RunAsync(qsim, args);

            return(value.ToExecutionResult());
        }
예제 #4
0
        /// <summary>
        ///     Simulates an operation given a string with its name and a JSON
        ///     encoding of its arguments.
        /// </summary>
        public async Task <ExecutionResult> RunAsync(string input, IChannel channel)
        {
            var inputParameters = ParseInputParameters(input, firstParameterInferredName: ParameterNameOperationName);

            var name   = inputParameters.DecodeParameter <string>(ParameterNameOperationName);
            var symbol = SymbolResolver.Resolve(name) as IQSharpSymbol;

            if (symbol == null)
            {
                throw new InvalidOperationException($"Invalid operation name: {name}");
            }

            using var qsim = new QuantumSimulator()
                             .WithJupyterDisplay(channel, ConfigurationSource)
                             .WithStackTraceDisplay(channel);
            var value = await symbol.Operation.RunAsync(qsim, inputParameters);

            return(value.ToExecutionResult());
        }
예제 #5
0
        public async Task <ExecutionResult> RunAsync(string input, IChannel channel, CancellationToken?token = null)
        {
            var inputParameters = ParseInputParameters(input, firstParameterInferredName: ParameterNameOperationName);

            var name = inputParameters.DecodeParameter <string>(ParameterNameOperationName);

            var symbol = SymbolResolver.Resolve(name) as IQSharpSymbol;

            if (symbol == null)
            {
                throw new InvalidOperationException($"Invalid operation name: {name}");
            }

            var session           = Guid.NewGuid();
            var debugSessionDivId = session.ToString();

            lock (SessionAdvanceEvents)
            {
                SessionAdvanceEvents[session] = new ManualResetEvent(true);
            }

            // Set up the simulator and execution path tracer
            var tracer = new ExecutionPathTracer.ExecutionPathTracer();

            using var qsim = new QuantumSimulator()
                             .WithExecutionPathTracer(tracer);

            // Render the placeholder for the debug UX.
            channel.Stdout($"Starting debug session for {name}...");
            channel.Display(new DisplayableHtmlElement($@"<div id='{debugSessionDivId}' />"));

            channel.SendIoPubMessage(
                new Message
            {
                Header = new MessageHeader
                {
                    MessageType = "iqsharp_debug_sessionstart"
                },
                Content = new DebugSessionContent
                {
                    DivId        = debugSessionDivId,
                    DebugSession = session.ToString(),
                }
            }
                );

            // Render the placeholder for the execution path.
            var executionPathDivId = $"execution-path-container-{Guid.NewGuid()}";

            channel.Display(new DisplayableHtmlElement($"<div id='{executionPathDivId}' />"));

            // Set up the OnOperationStart handler.
            qsim.OnOperationStart += (callable, args) =>
            {
                if (!(token ?? CancellationTokenSource.Token).IsCancellationRequested)
                {
                    var allocatedQubitsCount = (int)(qsim.QubitManager?.AllocatedQubitsCount ?? 0);
                    if (allocatedQubitsCount == 0)
                    {
                        return;
                    }

                    // Tell the IOPub channel that we're starting a new operation.
                    channel.SendIoPubMessage(
                        new Message
                    {
                        Header = new MessageHeader
                        {
                            MessageType = "iqsharp_debug_opstart"
                        },
                        Content = new DebugStatusContent
                        {
                            DebugSession = session.ToString(),
                            State        = new DisplayableState
                            {
                                QubitIds   = qsim.QubitIds.Select(q => (int)q),
                                NQubits    = allocatedQubitsCount,
                                Amplitudes = new DebugStateDumper(qsim).GetAmplitudes(),
                                DivId      = debugSessionDivId
                            }
                        }
                    }
                        );
                }
                WaitForAdvance(session, token).Wait();
            };

            qsim.OnOperationEnd += (callable, args) =>
            {
                if (!(token ?? CancellationTokenSource.Token).IsCancellationRequested)
                {
                    // Render the `ExecutionPath` traced out by the `ExecutionPathTracer`
                    tracer.RenderExecutionPath(
                        channel,
                        executionPathDivId,
                        renderDepth: 1,
                        this.ConfigurationSource.TraceVisualizationStyle);
                }
            };

            try
            {
                // Simulate the operation.
                var value = await Task.Run(() => symbol.Operation.RunAsync(qsim, inputParameters), token ?? CancellationTokenSource.Token);

                return(value.ToExecutionResult());
            }
            finally
            {
                // Report completion.
                channel.Stdout($"Finished debug session for {name}.");
                channel.SendIoPubMessage(
                    new Message
                {
                    Header = new MessageHeader
                    {
                        MessageType = "iqsharp_debug_sessionend"
                    },
                    Content = new DebugSessionContent
                    {
                        DivId        = debugSessionDivId,
                        DebugSession = session.ToString(),
                    }
                }
                    );
            }
        }
예제 #6
0
        /// <summary>
        ///     Outputs a visualization of a runtime execution path of an operation given
        ///     a string with its name and a JSON encoding of its arguments.
        /// </summary>
        public async Task <ExecutionResult> RunAsync(string input, IChannel channel)
        {
            // Parse input parameters
            var inputParameters = ParseInputParameters(input, firstParameterInferredName: ParameterNameOperationName);

            var name   = inputParameters.DecodeParameter <string>(ParameterNameOperationName);
            var symbol = SymbolResolver.Resolve(name) as IQSharpSymbol;

            if (symbol == null)
            {
                throw new InvalidOperationException($"Invalid operation name: {name}");
            }

            var depth = inputParameters.DecodeParameter <int>(
                ParameterNameDepth,
                defaultValue: this.ConfigurationSource.TraceVisualizationDefaultDepth
                );

            if (depth <= 0)
            {
                throw new ArgumentOutOfRangeException($"Invalid depth: {depth}. Must be >= 1.");
            }

            var tracer = new ExecutionPathTracer.ExecutionPathTracer();

            // Simulate operation and attach `ExecutionPathTracer` to trace out operations performed
            // in its execution path
            using var qsim = new QuantumSimulator()
                             .WithJupyterDisplay(channel, ConfigurationSource)
                             .WithStackTraceDisplay(channel)
                             .WithExecutionPathTracer(tracer);
            var value = await symbol.Operation.RunAsync(qsim, inputParameters);

            // Retrieve the `ExecutionPath` traced out by the `ExecutionPathTracer`
            var executionPath = tracer.GetExecutionPath();

            // Convert executionPath to JToken for serialization
            var executionPathJToken = JToken.FromObject(executionPath,
                                                        new JsonSerializer()
            {
                NullValueHandling = NullValueHandling.Ignore
            });

            // Render empty div with unique ID as cell output
            var divId   = $"execution-path-container-{Guid.NewGuid().ToString()}";
            var content = new ExecutionPathVisualizerContent(
                executionPathJToken,
                divId,
                depth,
                this.ConfigurationSource.TraceVisualizationStyle
                );

            channel.DisplayUpdatable(new DisplayableHtmlElement($"<div id='{divId}' />"));

            // Send execution path to JavaScript via iopub for rendering
            channel.SendIoPubMessage(
                new Message
            {
                Header = new MessageHeader
                {
                    MessageType = "render_execution_path"
                },
                Content = content,
            }
                );

            return(ExecuteStatus.Ok.ToExecutionResult());
        }