From f5796d1ead41967abf85f233357d77d855056864 Mon Sep 17 00:00:00 2001 From: Christopher Granade Date: Mon, 2 Mar 2020 15:00:50 -0800 Subject: [PATCH 1/2] Document all public APIs in Jupyter.csproj. --- src/Jupyter/ChannelWithNewLines.cs | 47 ++++++++- src/Jupyter/ConfigurationSource.cs | 48 ++++++++- src/Jupyter/Extensions.cs | 54 ++++++++++ src/Jupyter/Jupyter.csproj | 1 + src/Jupyter/KernelProperties.cs | 6 +- src/Jupyter/Magic/AbstractMagic.cs | 22 ++++- src/Jupyter/Magic/ConfigMagic.cs | 13 +++ src/Jupyter/Magic/EstimateMagic.cs | 24 ++++- src/Jupyter/Magic/PackageMagic.cs | 18 ++++ src/Jupyter/Magic/PerformanceMagic.cs | 8 ++ src/Jupyter/Magic/Simulate.cs | 23 +++++ src/Jupyter/Magic/ToffoliMagic.cs | 1 + src/Jupyter/Magic/WhoMagic.cs | 17 +++- src/Jupyter/Magic/WorkspaceMagic.cs | 13 ++- src/Jupyter/MagicResolver.cs | 5 + src/Jupyter/SymbolEncoders.cs | 10 ++ src/Jupyter/SymbolResolver.cs | 27 ++++- .../Visualization/DataTableEncoders.cs | 20 ++++ .../Visualization/StateDisplayEncoders.cs | 98 ++++++++++++++++++- .../Visualization/StateDisplayOperations.cs | 54 +++++++++- .../Visualization/TaskStatusEncoders.cs | 32 ++++++ 21 files changed, 525 insertions(+), 16 deletions(-) diff --git a/src/Jupyter/ChannelWithNewLines.cs b/src/Jupyter/ChannelWithNewLines.cs index b224a419aa..d140f55b12 100644 --- a/src/Jupyter/ChannelWithNewLines.cs +++ b/src/Jupyter/ChannelWithNewLines.cs @@ -9,27 +9,72 @@ namespace Microsoft.Quantum.IQSharp.Jupyter { /// - /// This is a Jupyter Core IChannel that wraps an existing IChannel and + /// This is a Jupyter Core IChannel that wraps an existing IChannel and /// adds NewLine symbols (\\n) /// to every message that gets logged to Stdout and Stderror. /// public class ChannelWithNewLines : IChannel { + /// + /// The existing channel that this channel wraps with new lines. + /// public IChannel BaseChannel { get; } + /// + /// Constructs a new channel, given a base channel to be wrapped + /// with newlines. + /// public ChannelWithNewLines(IChannel original) { BaseChannel = original; } + /// + /// Formats a given message for display to stdout or stderr. + /// + /// The message to be formatted. + /// + /// , formatted with a trailing newline + /// (\n). + /// public static string Format(string msg) => $"{msg}\n"; + /// + /// Writes a given message to the base channel's standard output, + /// but with a trailing newline appended. + /// + /// The message to be written. public void Stdout(string message) => BaseChannel?.Stdout(Format(message)); + /// + /// Writes a given message to the base channel's standard error, + /// but with a trailing newline appended. + /// + /// The message to be written. public void Stderr(string message) => BaseChannel?.Stderr(Format(message)); + /// + /// Displays a given object using the base channel. + /// + /// The object to be displayed. + /// + /// Note that no newline is appended by this method, as the + /// displayable object need not be a string. + /// public void Display(object displayable) => BaseChannel?.Display(displayable); + /// + /// Displays a given object using the base channel, allowing for + /// future updates. + /// + /// The object to be displayed. + /// + /// Note that no newline is appended by this method, as the + /// displayable object need not be a string. + /// + /// + /// An object that can be used to update the display in the future. + /// public IUpdatableDisplay DisplayUpdatable(object displayable) => BaseChannel?.DisplayUpdatable(displayable); } } diff --git a/src/Jupyter/ConfigurationSource.cs b/src/Jupyter/ConfigurationSource.cs index 34a571ea26..20bff003d7 100644 --- a/src/Jupyter/ConfigurationSource.cs +++ b/src/Jupyter/ConfigurationSource.cs @@ -12,10 +12,23 @@ namespace Microsoft.Quantum.IQSharp.Jupyter { + /// + /// A service that controls configuration options, such as those set + /// by preferences, the %config magic command, and so forth. + /// public interface IConfigurationSource { + /// + /// A dictionary of configuration options available from this + /// source. + /// IDictionary Configuration { get; } + /// + /// Persists the current configuration to disk such that a future + /// kernel session launched for the same notebook has the given + /// configuration. + /// void Persist(); private T GetOptionOrDefault(string optionName, T defaultValue) => @@ -23,24 +36,52 @@ private T GetOptionOrDefault(string optionName, T defaultValue) => ? token.ToObject() : defaultValue; + /// + /// The labeling convention to be used when labeling computational + /// basis states. + /// public BasisStateLabelingConvention BasisStateLabelingConvention => GetOptionOrDefault("dump.basisStateLabelingConvention", BasisStateLabelingConvention.LittleEndian); + /// + /// Whether small amplitudes should be truncated when dumping + /// states. + /// public bool TruncateSmallAmplitudes => GetOptionOrDefault("dump.truncateSmallAmplitudes", false); + /// + /// The threshold for truncating measurement probabilities when + /// dumping states. Computational basis states whose measurement + /// probabilities (i.e: squared magnitudes) are below this threshold + /// are subject to truncation when + /// + /// is true. + /// public double TruncationThreshold => GetOptionOrDefault("dump.truncationThreshold", 1e-10); } + /// + /// An implementation of the + /// + /// service interface that loads and persists configuration values from + /// and to a local JSON file. + /// public class ConfigurationSource : IConfigurationSource { + /// public IDictionary Configuration => _Configuration; private readonly IDictionary _Configuration; private string ConfigPath => Path.Join(Directory.GetCurrentDirectory(), ".iqsharp-config.json"); + /// + /// Constructs a new configuration source, loading initial + /// configuration options from the file .iqsharp-config.json, + /// if that file exists. + /// public ConfigurationSource(bool skipLoading = false) { // Try loading configuration from a JSON file in the current working @@ -51,7 +92,8 @@ public ConfigurationSource(bool skipLoading = false) _Configuration = JsonConvert.DeserializeObject>( configContents, JsonConverters.TupleConverters - ); + )!; // ← NB: We assert null here, since deserializing will + // throw an exception rather than silently failing. } else { @@ -59,6 +101,10 @@ public ConfigurationSource(bool skipLoading = false) } } + /// + /// Persists the current configuration to + /// .iqsharp-config.json. + /// public void Persist() { // Try writing the configuration back to JSON. diff --git a/src/Jupyter/Extensions.cs b/src/Jupyter/Extensions.cs index d8852715c6..fa309e6173 100644 --- a/src/Jupyter/Extensions.cs +++ b/src/Jupyter/Extensions.cs @@ -13,6 +13,9 @@ namespace Microsoft.Quantum.IQSharp.Jupyter { + /// + /// Extension methods to be used with various IQ# and Jupyter objects. + /// public static class Extensions { /// @@ -22,6 +25,10 @@ public static class Extensions public static ChannelWithNewLines WithNewLines(this IChannel original) => (original is ChannelWithNewLines ch) ? ch : new ChannelWithNewLines(original); + /// + /// Adds services required for the IQ# kernel to a given service + /// collection. + /// public static void AddIQSharpKernel(this IServiceCollection services) { services.AddSingleton(); @@ -29,6 +36,11 @@ public static void AddIQSharpKernel(this IServiceCollection services) services.AddSingleton(); } + /// + /// Given a configuration source, applies an action if that + /// configuration source defines a value for a particular + /// configuration key. + /// internal static IConfigurationSource ApplyConfiguration( this IConfigurationSource configurationSource, string keyName, Action action @@ -50,6 +62,15 @@ internal static IConfigurationSource ApplyConfiguration( (1L << 10, "KiB") }.ToImmutableList(); + /// + /// Given a number of bytes, formats that number as a human + /// readable string by appending unit suffixes (i.e.: indicating + /// kilobytes, megabytes, etc.). + /// + /// A number of bytes to be formatted. + /// + /// The number of bytes formatted as a human-readable string. + /// public static string ToHumanReadableBytes(this long nBytes) { foreach (var (scale, suffix) in byteSuffixes) @@ -64,11 +85,42 @@ public static string ToHumanReadableBytes(this long nBytes) return $"{nBytes} B"; } + /// + /// Adds functionality to a given quantum simulator to display + /// diagnostic output with rich Jupyter formatting. + /// + /// + /// The simulator to be augmented with Jupyter display + /// functionality. + /// + /// + /// The Jupyter display channel to be used to display diagnostic + /// output. + /// + /// + /// A source of configuration options to be used to set display + /// preferences. Typically, this will be provided by the service + /// provider configured when an execution engine is constructed. + /// + /// + /// The value of . + /// public static QuantumSimulator WithJupyterDisplay(this QuantumSimulator simulator, IChannel channel, IConfigurationSource configurationSource) { + // First, we disable console-based logging so as to not + // duplicate messages. simulator.DisableLogToConsole(); + // Next, we attach the display channel's standard output handling + // to the log event. simulator.OnLog += channel.Stdout; + // Next, we register the generic version of the DumpMachine callable + // as an ICallable with the simulator. Below, we'll provide our + // implementation of DumpMachine with the channel and configuration + // source we got as arguments. At the moment, there's no direct + // way to do this when registering an implementation, so we instead + // get an instance of the newly registered callable and set its + // properties accordingly. simulator.Register( typeof(Diagnostics.DumpMachine<>), typeof(JupyterDumpMachine<>), signature: typeof(ICallable) @@ -82,6 +134,8 @@ public static QuantumSimulator WithJupyterDisplay(this QuantumSimulator simulato ((JupyterDumpMachine)concreteOp).Channel = channel; ((JupyterDumpMachine)concreteOp).ConfigurationSource = configurationSource; + // Next, we repeat the whole process for DumpRegister instead of + // DumpMachine. simulator.Register( typeof(Diagnostics.DumpRegister<>), typeof(JupyterDumpRegister<>), signature: typeof(ICallable) diff --git a/src/Jupyter/Jupyter.csproj b/src/Jupyter/Jupyter.csproj index 87af37c2dd..848edf51d7 100644 --- a/src/Jupyter/Jupyter.csproj +++ b/src/Jupyter/Jupyter.csproj @@ -5,6 +5,7 @@ x64 Microsoft.Quantum.IQSharp.Jupyter Microsoft.Quantum.IQSharp.Jupyter + true diff --git a/src/Jupyter/KernelProperties.cs b/src/Jupyter/KernelProperties.cs index d29dd350a4..8777bcf7d0 100644 --- a/src/Jupyter/KernelProperties.cs +++ b/src/Jupyter/KernelProperties.cs @@ -10,6 +10,10 @@ namespace Microsoft.Quantum.IQSharp.Jupyter /// public static class Constants { + /// + /// The properties for this kernel (e.g. versions, language name, + /// etc.). + /// public static readonly KernelProperties IQSharpKernelProperties = new KernelProperties { FriendlyName = "Q#", @@ -18,7 +22,7 @@ public static class Constants DisplayName = "Q#", LanguageName = "qsharp", - LanguageVersion = "0.4", + LanguageVersion = "0.10", LanguageMimeType = "text/x-qsharp", LanguageFileExtension = ".qs", diff --git a/src/Jupyter/Magic/AbstractMagic.cs b/src/Jupyter/Magic/AbstractMagic.cs index e8020842f7..999d8b4824 100644 --- a/src/Jupyter/Magic/AbstractMagic.cs +++ b/src/Jupyter/Magic/AbstractMagic.cs @@ -10,8 +10,14 @@ namespace Microsoft.Quantum.IQSharp.Jupyter { + /// + /// Abstract base class for IQ# magic symbols. + /// public abstract class AbstractMagic : MagicSymbol { + /// + /// Constructs a new magic symbol given its name and documentation. + /// public AbstractMagic(string keyword, Documentation docs) { this.Name = $"%{keyword}"; @@ -21,7 +27,14 @@ public AbstractMagic(string keyword, Documentation docs) this.Execute = SafeExecute(this.Run); } - public Func SafeExecute(Func magic) => + /// + /// Given a function representing the execution of a magic command, + /// returns a new function that executes + /// and catches any exceptions that occur during execution. The + /// returned execution function displays the given exceptions to its + /// display channel. + /// + public Func SafeExecute(Func magic) => (input, channel) => { channel = channel.WithNewLines(); @@ -47,6 +60,10 @@ public Func SafeExecute(Func + /// Parses the input to a magic command, interpreting the input as + /// a name followed by a JSON-serialized dictionary. + /// public static (string, Dictionary) ParseInput(string input) { if (input == null) return (string.Empty, new Dictionary { }); @@ -61,6 +78,9 @@ public static (string, Dictionary) ParseInput(string input) return (name, args); } + /// + /// A method to be run when the magic command is executed. + /// public abstract ExecutionResult Run(string input, IChannel channel); } } diff --git a/src/Jupyter/Magic/ConfigMagic.cs b/src/Jupyter/Magic/ConfigMagic.cs index 900d87295d..7dd95e7337 100644 --- a/src/Jupyter/Magic/ConfigMagic.cs +++ b/src/Jupyter/Magic/ConfigMagic.cs @@ -13,8 +13,15 @@ namespace Microsoft.Quantum.IQSharp.Jupyter { + /// + /// A magic command that sets or queries configuration options. + /// public class ConfigMagic : AbstractMagic { + /// + /// Constructs a magic command that sets or queries configuration + /// options using a given configuration source. + /// public ConfigMagic(IConfigurationSource configurationSource) : base( "config", new Documentation { @@ -24,8 +31,14 @@ public ConfigMagic(IConfigurationSource configurationSource) : base( this.ConfigurationSource = configurationSource; } + /// + /// The configuration source which this magic command queries or + /// sets configuration options in. + /// public IConfigurationSource ConfigurationSource { get; } + + /// public override ExecutionResult Run(string? input, IChannel channel) { // If we didn't get any input, treat it as a query. diff --git a/src/Jupyter/Magic/EstimateMagic.cs b/src/Jupyter/Magic/EstimateMagic.cs index d49b1ba10b..ae8e2c668b 100644 --- a/src/Jupyter/Magic/EstimateMagic.cs +++ b/src/Jupyter/Magic/EstimateMagic.cs @@ -12,23 +12,43 @@ namespace Microsoft.Quantum.IQSharp.Jupyter { + /// + /// A magic command that performs resource estimation on functions and + /// operations. + /// public class EstimateMagic : AbstractMagic { + /// + /// Given a symbol resolver that can be used to locate operations, + /// constructs a new magic command that performs resource estimation + /// on resolved operations. + /// public EstimateMagic(ISymbolResolver resolver) : base( "estimate", - new Documentation { - Summary = "Runs a given function or operation on the QuantumSimulator target machine" + new Documentation + { + Summary = "Runs a given function or operation on the ResourcesEstimator target machine." }) { this.SymbolResolver = resolver; } + /// + /// The symbol resolver that this magic command uses to locate + /// operations. + /// public ISymbolResolver SymbolResolver { get; } + /// public override ExecutionResult Run(string input, IChannel channel) => RunAsync(input, channel).Result; + /// + /// Given an input representing the name of an operation and a JSON + /// serialization of its inputs, returns a task that can be awaited + /// on for resource estimates from running that operation. + /// public async Task RunAsync(string input, IChannel channel) { var (name, args) = ParseInput(input); diff --git a/src/Jupyter/Magic/PackageMagic.cs b/src/Jupyter/Magic/PackageMagic.cs index 2fb53087c6..4fad99d1ee 100644 --- a/src/Jupyter/Magic/PackageMagic.cs +++ b/src/Jupyter/Magic/PackageMagic.cs @@ -10,8 +10,16 @@ namespace Microsoft.Quantum.IQSharp.Jupyter { + /// + /// A magic command that can be used to add new NuGet packages to the + /// current IQ# session. + /// public class PackageMagic : AbstractMagic { + /// + /// Constructs a new magic command that adds package references to + /// a given references collection. + /// public PackageMagic(IReferences references) : base( "package", new Documentation { @@ -21,8 +29,13 @@ public PackageMagic(IReferences references) : base( this.References = references; } + /// + /// The references collection that this magic command adds package + /// references to. + /// public IReferences References { get; } + /// public override ExecutionResult Run(string input, IChannel channel) { var (name, _) = ParseInput(input); @@ -49,6 +62,11 @@ public override ExecutionResult Run(string input, IChannel channel) return task.Result; } + /// + /// Adds a package given a string representing its name and returns + /// a task that can be awaited on for the completion of the package + /// download. + /// public async Task RunAsync(string name, IChannel channel, Action statusCallback) { if (!string.IsNullOrWhiteSpace(name)) diff --git a/src/Jupyter/Magic/PerformanceMagic.cs b/src/Jupyter/Magic/PerformanceMagic.cs index 75bfd101dc..85320366aa 100644 --- a/src/Jupyter/Magic/PerformanceMagic.cs +++ b/src/Jupyter/Magic/PerformanceMagic.cs @@ -14,8 +14,15 @@ namespace Microsoft.Quantum.IQSharp.Jupyter { + /// + /// A magic command that reports various performance metrics to the + /// user. + /// public class PerformanceMagic : AbstractMagic { + /// + /// Constructs a new performance command. + /// public PerformanceMagic() : base( "performance", new Documentation { @@ -24,6 +31,7 @@ public PerformanceMagic() : base( { } + /// public override ExecutionResult Run(string? input, IChannel channel) { var currentProcess = Process.GetCurrentProcess(); diff --git a/src/Jupyter/Magic/Simulate.cs b/src/Jupyter/Magic/Simulate.cs index 1584848e4e..495dcadce6 100644 --- a/src/Jupyter/Magic/Simulate.cs +++ b/src/Jupyter/Magic/Simulate.cs @@ -11,8 +11,17 @@ namespace Microsoft.Quantum.IQSharp.Jupyter { + /// + /// A magic command that can be used to simulate operations and functions + /// on a full-state quantum simulator. + /// public class SimulateMagic : AbstractMagic { + /// + /// Constructs a new magic command given a resolver used to find + /// operations and functions, and a configuration source used to set + /// configuration options. + /// public SimulateMagic(ISymbolResolver resolver, IConfigurationSource configurationSource) : base( "simulate", new Documentation { @@ -23,12 +32,26 @@ public SimulateMagic(ISymbolResolver resolver, IConfigurationSource configuratio this.ConfigurationSource = configurationSource; } + /// + /// The symbol resolver used by this magic command to find + /// operations or functions to be simulated. + /// public ISymbolResolver SymbolResolver { get; } + + /// + /// The configuration source used by this magic command to control + /// simulation options (e.g.: dump formatting options). + /// public IConfigurationSource ConfigurationSource { get; } + /// public override ExecutionResult Run(string input, IChannel channel) => RunAsync(input, channel).Result; + /// + /// Simulates an operation given a string with its name and a JSON + /// encoding of its arguments. + /// public async Task RunAsync(string input, IChannel channel) { var (name, args) = ParseInput(input); diff --git a/src/Jupyter/Magic/ToffoliMagic.cs b/src/Jupyter/Magic/ToffoliMagic.cs index 8cd7285432..b63ec1cb02 100644 --- a/src/Jupyter/Magic/ToffoliMagic.cs +++ b/src/Jupyter/Magic/ToffoliMagic.cs @@ -32,6 +32,7 @@ public ToffoliMagic(ISymbolResolver resolver) : base( /// public ISymbolResolver SymbolResolver { get; } + /// public override ExecutionResult Run(string input, IChannel channel) => RunAsync(input, channel).Result; diff --git a/src/Jupyter/Magic/WhoMagic.cs b/src/Jupyter/Magic/WhoMagic.cs index 3cd3ef2844..d8c4e9ed23 100644 --- a/src/Jupyter/Magic/WhoMagic.cs +++ b/src/Jupyter/Magic/WhoMagic.cs @@ -9,19 +9,32 @@ namespace Microsoft.Quantum.IQSharp.Jupyter { + /// + /// A magic command that can be used to query the functions and operations + /// defined within an IQ# session. + /// public class WhoMagic : AbstractMagic { + /// + /// Given a given snippets collection, constructs a new magic command + /// that queries callables defined in that snippets collection. + /// public WhoMagic(ISnippets snippets) : base( - "who", - new Documentation { + "who", + new Documentation + { Summary = "Provides actions related to the current workspace." }) { this.Snippets = snippets; } + /// + /// The snippets collection queried by this magic command. + /// public ISnippets Snippets { get; } + /// public override ExecutionResult Run(string input, IChannel channel) => Snippets.Operations .Select(op => op.FullName) diff --git a/src/Jupyter/Magic/WorkspaceMagic.cs b/src/Jupyter/Magic/WorkspaceMagic.cs index 4735c4eaf2..190605540c 100644 --- a/src/Jupyter/Magic/WorkspaceMagic.cs +++ b/src/Jupyter/Magic/WorkspaceMagic.cs @@ -9,8 +9,15 @@ namespace Microsoft.Quantum.IQSharp.Jupyter { + /// + /// A magic symbol that provides access to a given workspace. + /// public class WorkspaceMagic : AbstractMagic { + /// + /// Given a workspace, constructs a new magic symbol to control + /// that workspace. + /// public WorkspaceMagic(IWorkspace workspace) : base( "workspace", new Documentation { @@ -20,10 +27,13 @@ public WorkspaceMagic(IWorkspace workspace) : base( this.Workspace = workspace; } + /// + /// The workspace controlled by this magic symbol. + /// public IWorkspace Workspace { get; } /// - /// Performs checks to verify if the Workspace is avaialble and in a success (no errors) state. + /// Performs checks to verify if the Workspace is available and in a success (no errors) state. /// The method throws Exceptions if it finds it is not ready to execute. /// public void CheckIfReady() @@ -38,6 +48,7 @@ public void CheckIfReady() } } + /// public override ExecutionResult Run(string input, IChannel channel) { var (command, _) = ParseInput(input); diff --git a/src/Jupyter/MagicResolver.cs b/src/Jupyter/MagicResolver.cs index d1e78613e1..7d30e7d0a4 100644 --- a/src/Jupyter/MagicResolver.cs +++ b/src/Jupyter/MagicResolver.cs @@ -28,6 +28,11 @@ public class MagicSymbolResolver : ISymbolResolver private IReferences references; private ILogger logger; + /// + /// Constructs a new magic symbol resolver using the provided + /// services to search assembly references for subclasses of + /// . + /// public MagicSymbolResolver(IServiceProvider services, ILogger logger) { this.cache = new Dictionary(); diff --git a/src/Jupyter/SymbolEncoders.cs b/src/Jupyter/SymbolEncoders.cs index 7688b827a7..7fecf52adf 100644 --- a/src/Jupyter/SymbolEncoders.cs +++ b/src/Jupyter/SymbolEncoders.cs @@ -13,8 +13,13 @@ namespace Microsoft.Quantum.IQSharp.Jupyter /// public class IQSharpSymbolToTextResultEncoder : IResultEncoder { + /// public string MimeType => MimeTypes.PlainText; + /// + /// Checks if a displayable object is an IQ# symbol, and if so, + /// returns an encoding of that symbol into plain text. + /// public EncodedData? Encode(object displayable) { if (displayable is IQSharpSymbol symbol) @@ -33,8 +38,13 @@ public class IQSharpSymbolToTextResultEncoder : IResultEncoder /// public class IQSharpSymbolToHtmlResultEncoder : IResultEncoder { + /// public string MimeType => MimeTypes.Html; + /// + /// Checks if a displayable object is an IQ# symbol, and if so, + /// returns an encoding of that symbol into HTML. + /// public EncodedData? Encode(object displayable) { if (displayable is IQSharpSymbol symbol) diff --git a/src/Jupyter/SymbolResolver.cs b/src/Jupyter/SymbolResolver.cs index 7e85a111d5..abbac63984 100644 --- a/src/Jupyter/SymbolResolver.cs +++ b/src/Jupyter/SymbolResolver.cs @@ -20,25 +20,44 @@ namespace Microsoft.Quantum.IQSharp.Jupyter [JsonObject(MemberSerialization.OptIn)] public class IQSharpSymbol : ISymbol { + /// + /// The information provided by the compiler about the operation + /// represented by this symbol. + /// [JsonIgnore] public OperationInfo Operation { get; } + /// + /// The name of the operation represented by this symbol. + /// [JsonProperty("name")] - public string Name => - Operation.FullName; + public string Name => Operation.FullName; // TODO: serialize as stringenum. + /// [JsonProperty("kind")] public SymbolKind Kind { get; private set; } + /// + /// The source file in which the operation represented by this + /// symbol was defined. + /// [JsonProperty("source")] public string Source => Operation.Header.SourceFile.Value; + /// + /// The documentation for this symbol, as provided by its API + /// documentation comments. + /// [JsonProperty("documentation")] public string Documentation => String.Join("\n", Operation.Header.Documentation); // TODO: expose documentation here. + /// + /// Constructs a new symbol given information about an operation + /// as provided by the Q# compiler. + /// public IQSharpSymbol(OperationInfo op) { if (op == null) { throw new ArgumentNullException(nameof(op)); } @@ -59,8 +78,8 @@ public class SymbolResolver : ISymbolResolver /// Constructs a new resolver that looks for symbols in a given /// collection of snippets. /// - /// - /// The collection of snippets to be used when resolving symbols. + /// + /// An object to be used to resolve operation names to symbols. /// public SymbolResolver(IOperationResolver opsResolver) { diff --git a/src/Jupyter/Visualization/DataTableEncoders.cs b/src/Jupyter/Visualization/DataTableEncoders.cs index fad8bc5002..d20fc5ecff 100644 --- a/src/Jupyter/Visualization/DataTableEncoders.cs +++ b/src/Jupyter/Visualization/DataTableEncoders.cs @@ -29,22 +29,42 @@ internal static Table AsJupyterTable(this DataTable table) => }; } + /// + /// Encodes instances as HTML + /// tables. + /// public class DataTableToHtmlEncoder : IResultEncoder { private static readonly IResultEncoder tableEncoder = new TableToHtmlDisplayEncoder(); + + /// public string MimeType => MimeTypes.Html; + /// + /// Checks if a displayable object represents a data table, and if + /// so, returns an encoding into an HTML table. + /// public EncodedData? Encode(object displayable) => displayable is DataTable table ? tableEncoder.Encode(table.AsJupyterTable()) : null; } + /// + /// Encodes instances as plain-text + /// tables. + /// public class DataTableToTextEncoder : IResultEncoder { private static readonly IResultEncoder tableEncoder = new TableToTextDisplayEncoder(); + + /// public string MimeType => MimeTypes.PlainText; + /// + /// Checks if a displayable object represents a data table, and if + /// so, returns an encoding into a plain-text table. + /// public EncodedData? Encode(object displayable) => displayable is DataTable table ? tableEncoder.Encode(table.AsJupyterTable()) diff --git a/src/Jupyter/Visualization/StateDisplayEncoders.cs b/src/Jupyter/Visualization/StateDisplayEncoders.cs index 776babbffe..29838273c2 100644 --- a/src/Jupyter/Visualization/StateDisplayEncoders.cs +++ b/src/Jupyter/Visualization/StateDisplayEncoders.cs @@ -15,14 +15,47 @@ namespace Microsoft.Quantum.IQSharp.Jupyter { + /// + /// The convention to be used in labeling computational basis states + /// given their representations as strings of classical bits. + /// [JsonConverter(typeof(StringEnumConverter))] public enum BasisStateLabelingConvention { + /// + /// Label computational states directly by their bit strings. + /// + /// + /// Following this convention, the state |0⟩ ⊗ |1⟩ ⊗ |1⟩ is labeled + /// by |011⟩. + /// Bitstring, + + /// + /// Label computational states directly by interpreting their bit + /// strings as little-endian encoded integers. + /// + /// + /// Following this convention, the state |0⟩ ⊗ |1⟩ ⊗ |1⟩ is labeled + /// by |6⟩. + /// LittleEndian, + + /// + /// Label computational states directly by interpreting their bit + /// strings as big-endian encoded integers. + /// + /// + /// Following this convention, the state |0⟩ ⊗ |1⟩ ⊗ |1⟩ is labeled + /// by |3⟩. + /// BigEndian } + /// + /// Represents a quantum state vector and all metadata needed to display + /// that state vector. + /// public class DisplayableState { private static readonly IComparer ToIntComparer = @@ -32,16 +65,29 @@ public class DisplayableState ) ); + /// + /// The indexes of each qubit on which this state is defined, or + /// null if these indexes are not known. + /// public IEnumerable? QubitIds { get; set; } + + /// + /// The number of qubits on which this state is defined. + /// public int NQubits { get; set; } - + /// /// These amplitudes represent the computational basis states - /// labeled in little-endian order, as per the behavior of + /// labeled in little-endian order, as per the behavior of /// . /// public Complex[]? Amplitudes { get; set; } + /// + /// An enumerable source of the significant amplitudes of this state + /// vector and their labels, where significance and labels are + /// defined by the values loaded from . + /// public IEnumerable<(Complex, string)> SignificantAmplitudes( IConfigurationSource configurationSource ) => SignificantAmplitudes( @@ -50,6 +96,21 @@ IConfigurationSource configurationSource configurationSource.TruncationThreshold ); + /// + /// An enumerable source of the significant amplitudes of this state + /// vector and their labels. + /// + /// + /// The convention to be used in labeling each computational basis state. + /// + /// + /// Whether to truncate small amplitudes. + /// + /// + /// If is true, + /// then amplitudes whose absolute value squared are below this + /// threshold are suppressed. + /// public IEnumerable<(Complex, string)> SignificantAmplitudes( BasisStateLabelingConvention convention, bool truncateSmallAmplitudes, double truncationThreshold @@ -77,6 +138,11 @@ IConfigurationSource configurationSource } ); + /// + /// Using the given labeling convention, returns the label for a + /// computational basis state described by its bit string as encoded + /// into an integer index in the little-endian encoding. + /// public string BasisStateLabel( BasisStateLabelingConvention convention, int index ) => convention switch @@ -104,16 +170,30 @@ public string BasisStateLabel( } + /// + /// A result encoder that displays quantum state vectors as HTML tables. + /// public class StateVectorToHtmlResultEncoder : IResultEncoder { private const double TWO_PI = 2.0 * System.Math.PI; + + /// public string MimeType => MimeTypes.Html; private IConfigurationSource ConfigurationSource; + + /// + /// Constructs a new result encoder using configuration settings + /// provided by a given configuration source. + /// public StateVectorToHtmlResultEncoder(IConfigurationSource configurationSource) { ConfigurationSource = configurationSource; } + /// + /// Checks if a given display object is a state vector, and if so, + /// returns its encoding into an HTML table. + /// public EncodedData? Encode(object displayable) { string StyleForAngle(double angle) => @@ -188,15 +268,29 @@ string StyleForAngle(double angle) => } } + /// + /// A result encoder that displays quantum state vectors as plain-text + /// tables. + /// public class StateVectorToTextResultEncoder : IResultEncoder { + /// public string MimeType => MimeTypes.PlainText; private IConfigurationSource ConfigurationSource; + + /// + /// Constructs a new result encoder using configuration settings + /// provided by a given configuration source. + /// public StateVectorToTextResultEncoder(IConfigurationSource configurationSource) { ConfigurationSource = configurationSource; } + /// + /// Checks if a given display object is a state vector, and if so, + /// returns its encoding into a plain-text table. + /// public EncodedData? Encode(object displayable) { if (displayable is DisplayableState vector) diff --git a/src/Jupyter/Visualization/StateDisplayOperations.cs b/src/Jupyter/Visualization/StateDisplayOperations.cs index e560340f8b..951a4056e6 100644 --- a/src/Jupyter/Visualization/StateDisplayOperations.cs +++ b/src/Jupyter/Visualization/StateDisplayOperations.cs @@ -14,18 +14,43 @@ namespace Microsoft.Quantum.IQSharp.Jupyter { + /// + /// A state dumper that encodes dumped states into Jupyter-display + /// objects. + /// public class JupyterDisplayDumper : QuantumSimulator.StateDumper { private readonly IChannel Channel; private long _count = -1; private Complex[]? _data = null; + /// + /// Whether small amplitudes should be truncated when dumping + /// states. + /// public bool TruncateSmallAmplitudes { get; set; } = false; + + /// + /// The threshold for truncating measurement probabilities when + /// dumping states. Computational basis states whose measurement + /// probabilities (i.e: squared magnitudes) are below this threshold + /// are subject to truncation when + /// + /// is true. + /// public double TruncationThreshold { get; set; } = 1e-10; - public BasisStateLabelingConvention BasisStateLabelingConvention { get; set; } = BasisStateLabelingConvention.Bitstring; + /// + /// The labeling convention to be used when labeling computational + /// basis states. + /// + public BasisStateLabelingConvention BasisStateLabelingConvention { get; set; } = BasisStateLabelingConvention.Bitstring; + /// + /// Sets the properties of this display dumper from a given + /// configuration source. + /// public JupyterDisplayDumper Configure(IConfigurationSource configurationSource) { configurationSource @@ -37,11 +62,19 @@ public JupyterDisplayDumper Configure(IConfigurationSource configurationSource) return this; } + /// + /// Constructs a new display dumper for a given simulator, using a + /// given Jupyter display channel to output dumped states. + /// public JupyterDisplayDumper(QuantumSimulator sim, IChannel channel) : base(sim) { Channel = channel; } + /// + /// Used by the simulator to provide states when dumping. + /// Not intended to be called directly. + /// public override bool Callback(uint idx, double real, double img) { if (_data == null) throw new Exception("Expected data buffer to be initialized before callback, but it was null."); @@ -49,6 +82,10 @@ public override bool Callback(uint idx, double real, double img) return true; } + /// + /// Dumps the state of a register of qubits as a Jupyter displayable + /// object. + /// public override bool Dump(IQArray? qubits = null) { _count = qubits == null @@ -84,17 +121,24 @@ internal static QVoid DumpToChannel(QuantumSimulator sim, IChannel channel, ICon } } + /// + /// An implementation of + /// that dumps the state of its target machine to a Jupyter-displayable + /// object. + /// public class JupyterDumpMachine : Microsoft.Quantum.Diagnostics.DumpMachine { private QuantumSimulator Simulator { get; } internal IConfigurationSource? ConfigurationSource = null; internal IChannel? Channel = null; + /// public JupyterDumpMachine(QuantumSimulator m) : base(m) { this.Simulator = m; } + /// public override Func Body => (location) => { if (location == null) { throw new ArgumentNullException(nameof(location)); } @@ -120,16 +164,24 @@ public JupyterDumpMachine(QuantumSimulator m) : base(m) }; } + /// + /// An implementation of + /// that dumps the state of its target machine to a Jupyter-displayable + /// object. + /// public class JupyterDumpRegister : Microsoft.Quantum.Diagnostics.DumpRegister { private QuantumSimulator Simulator { get; } internal IConfigurationSource? ConfigurationSource = null; internal IChannel? Channel = null; + + /// public JupyterDumpRegister(QuantumSimulator m) : base(m) { this.Simulator = m; } + /// public override Func<(T, IQArray), QVoid> Body => (input) => { var (location, qubits) = input; diff --git a/src/Jupyter/Visualization/TaskStatusEncoders.cs b/src/Jupyter/Visualization/TaskStatusEncoders.cs index d022f16bf8..1a65466a46 100644 --- a/src/Jupyter/Visualization/TaskStatusEncoders.cs +++ b/src/Jupyter/Visualization/TaskStatusEncoders.cs @@ -9,11 +9,26 @@ namespace Microsoft.Quantum.IQSharp.Jupyter { + /// + /// Represents the status of a task, including its description, + /// completion status, and possibly a subtask description. + /// public class TaskStatus { + /// + /// The last time at which the status was updated. + /// public DateTime LastUpdated { get; private set; } = DateTime.Now; + + /// + /// Whether the status represents a completed task. + /// public bool IsCompleted { get; set; } = false; private string _description = ""; + + /// + /// A description of the task represented by this object. + /// public string Description { get => _description; @@ -25,6 +40,13 @@ public string Description } private string? _subtask = null; + + /// + /// A description of the current subtask for this task (e.g. if + /// the task represents downloading multiple files, which file is + /// currently being downloaded). If there is no applicable subtask, + /// this property should be null. + /// public string? Subtask { get => _subtask; @@ -35,6 +57,9 @@ public string? Subtask } } + /// + /// Constructs a new status given the description of a task. + /// public TaskStatus(string description) { Description = description; @@ -46,8 +71,15 @@ public TaskStatus(string description) /// public class TaskStatusToTextEncoder : IResultEncoder { + /// + /// The MIME type returned by this encoder. + /// public string MimeType => MimeTypes.PlainText; + /// + /// Checks if a displayable object is a task status, and if so, + /// returns its encoding into plain text. + /// public EncodedData? Encode(object displayable) { if (displayable is TaskStatus status) From 11bc80b69811f928bfe03bb25e73f230cda54fb4 Mon Sep 17 00:00:00 2001 From: Chris Granade Date: Fri, 6 Mar 2020 15:46:40 -0800 Subject: [PATCH 2/2] Update src/Jupyter/ConfigurationSource.cs Co-Authored-By: Mariia Mykhailova --- src/Jupyter/ConfigurationSource.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Jupyter/ConfigurationSource.cs b/src/Jupyter/ConfigurationSource.cs index 9c7a850ca7..6bb5c1fb63 100644 --- a/src/Jupyter/ConfigurationSource.cs +++ b/src/Jupyter/ConfigurationSource.cs @@ -39,7 +39,7 @@ private T GetOptionOrDefault(string optionName, T defaultValue) => /// /// The labeling convention to be used when labeling computational - /// basis states. + /// basis states (bit string, little-endian or big-endian). /// public BasisStateLabelingConvention BasisStateLabelingConvention => GetOptionOrDefault("dump.basisStateLabelingConvention", BasisStateLabelingConvention.LittleEndian);