From 14717f6eaff808209117fb72cfb6aeca5d791b3a Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Tue, 26 May 2020 16:29:33 -0700 Subject: [PATCH 1/4] Add --dry-run option --- src/Simulation/EntryPointDriver/Azure.cs | 44 +++++++++++++++---- src/Simulation/EntryPointDriver/Driver.cs | 16 ++++++- .../EntryPointDriver/NothingMachine.cs | 9 ++-- 3 files changed, 53 insertions(+), 16 deletions(-) diff --git a/src/Simulation/EntryPointDriver/Azure.cs b/src/Simulation/EntryPointDriver/Azure.cs index b9edb7c5477..8d4ed79b2de 100644 --- a/src/Simulation/EntryPointDriver/Azure.cs +++ b/src/Simulation/EntryPointDriver/Azure.cs @@ -32,23 +32,44 @@ internal static async Task Submit( return 1; } - // TODO: Specify the number of shots. The IQuantumMachine interface should be updated. - var job = await machine.SubmitAsync(entryPoint.Info, entryPoint.CreateArgument(parseResult)); - switch (settings.Output) + var input = entryPoint.CreateArgument(parseResult); + if (settings.DryRun) + { + var (isValid, message) = machine.Validate(entryPoint.Info, input); + Console.WriteLine(isValid ? "✔️ The program is valid!" : "❌ The program is invalid."); + if (!string.IsNullOrWhiteSpace(message)) + { + Console.WriteLine(message); + } + return isValid ? 0 : 1; + } + else + { + // TODO: Specify the number of shots. + var job = await machine.SubmitAsync(entryPoint.Info, input); + DisplayJob(job, settings.Output); + return 0; + } + } + + /// + /// Displays the job using the output format. + /// + /// The job. + /// The output format. + /// Thrown if the output format is invalid. + private static void DisplayJob(IQuantumMachineJob job, OutputFormat format) + { + switch (format) { case OutputFormat.FriendlyUri: - Console.WriteLine("Job submitted. To track your job status and see the results use:"); - Console.WriteLine(); // TODO: Show the friendly URI. The friendly URI is not yet available from the job. - Console.WriteLine(job.Id); - break; case OutputFormat.Id: Console.WriteLine(job.Id); break; default: - throw new ArgumentOutOfRangeException($"Invalid output format '{settings.Output}'."); + throw new ArgumentOutOfRangeException($"Invalid output format '{format}'."); } - return 0; } /// @@ -140,6 +161,11 @@ internal sealed class AzureSettings /// public OutputFormat Output { get; set; } + /// + /// Validate the program and options, but do not submit to Azure Quantum. + /// + public bool DryRun { get; set; } + /// /// Creates a based on the settings. /// diff --git a/src/Simulation/EntryPointDriver/Driver.cs b/src/Simulation/EntryPointDriver/Driver.cs index 13ea4c1ee61..21c029dc403 100644 --- a/src/Simulation/EntryPointDriver/Driver.cs +++ b/src/Simulation/EntryPointDriver/Driver.cs @@ -8,6 +8,7 @@ using System.CommandLine.Invocation; using System.CommandLine.Parsing; using System.Linq; +using System.Text; using System.Threading.Tasks; using Microsoft.Quantum.QsCompiler.ReservedKeywords; using Microsoft.Quantum.Simulation.Core; @@ -84,6 +85,7 @@ public async Task Run(string[] args) AddOptionIfAvailable(submit, BaseUriOption); AddOptionIfAvailable(submit, OutputOption); AddOptionIfAvailable(submit, ShotsOption); + AddOptionIfAvailable(submit, DryRunOption); var root = new RootCommand(entryPoint.Summary) { simulate, submit }; foreach (var option in entryPoint.Options) @@ -98,6 +100,7 @@ public async Task Run(string[] args) } root.Handler = simulate.Handler; + Console.OutputEncoding = Encoding.UTF8; return await new CommandLineBuilder(root) .UseDefaults() .UseHelpBuilder(context => new QsHelpBuilder(context.Console)) @@ -131,9 +134,10 @@ private async Task Submit(ParseResult parseResult, AzureSettings settings) AadToken = DefaultIfShadowed(AadTokenOption, settings.AadToken), BaseUri = DefaultIfShadowed(BaseUriOption, settings.BaseUri), Shots = DefaultIfShadowed(ShotsOption, settings.Shots), - Output = DefaultIfShadowed(OutputOption, settings.Output) + Output = DefaultIfShadowed(OutputOption, settings.Output), + DryRun = DefaultIfShadowed(DryRunOption, settings.DryRun) }); - + /// /// Returns true if the alias is not already used by an entry point option. /// @@ -257,6 +261,14 @@ internal static class Driver new[] { "--output" }, OutputFormat.FriendlyUri, "The information to show in the output after the job is submitted."); + + /// + /// The dry run option. + /// + internal static readonly OptionInfo DryRunOption = new OptionInfo( + new[] { "--dry-run" }, + false, + "Validate the program and options, but do not submit to Azure Quantum."); } /// diff --git a/src/Simulation/EntryPointDriver/NothingMachine.cs b/src/Simulation/EntryPointDriver/NothingMachine.cs index d6513eaf77a..167f8341585 100644 --- a/src/Simulation/EntryPointDriver/NothingMachine.cs +++ b/src/Simulation/EntryPointDriver/NothingMachine.cs @@ -14,9 +14,9 @@ namespace Microsoft.Quantum.CsharpGeneration.EntryPointDriver /// internal class NothingMachine : IQuantumMachine { - public string ProviderId => nameof(NothingMachine); + public string ProviderId { get; } = nameof(NothingMachine); - public string Target => "Nothing"; + public string Target { get; } = "Nothing"; public Task> ExecuteAsync( EntryPointInfo info, TInput input) => @@ -81,8 +81,7 @@ public Task SubmitAsync( throw new NotSupportedException(); public (bool IsValid, string Message) Validate( - EntryPointInfo info, TInput input) => - throw new NotSupportedException(); + EntryPointInfo info, TInput input) => (true, string.Empty); /// /// A quantum machine job with default properties. @@ -99,7 +98,7 @@ private class DefaultJob : IQuantumMachineJob public bool Failed { get; } = true; - public Uri Uri => new Uri("https://example.com/" + Id); + public Uri Uri => new Uri($"https://www.example.com/{Id}"); public Task CancelAsync(CancellationToken cancellationToken = default) => throw new NotSupportedException(); From aa58f0087f75a441f9ae3d05f6ba5772891c38d8 Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Tue, 26 May 2020 17:30:20 -0700 Subject: [PATCH 2/4] Set shots in submission context --- src/Simulation/EntryPointDriver/Azure.cs | 14 ++++++++++++-- src/Simulation/EntryPointDriver/NothingMachine.cs | 4 ++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/Simulation/EntryPointDriver/Azure.cs b/src/Simulation/EntryPointDriver/Azure.cs index 8d4ed79b2de..10c80178d9f 100644 --- a/src/Simulation/EntryPointDriver/Azure.cs +++ b/src/Simulation/EntryPointDriver/Azure.cs @@ -45,8 +45,8 @@ internal static async Task Submit( } else { - // TODO: Specify the number of shots. - var job = await machine.SubmitAsync(entryPoint.Info, input); + var job = await machine.SubmitAsync( + entryPoint.Info, input, new SubmissionContext { Shots = settings.Shots }); DisplayJob(job, settings.Output); return 0; } @@ -93,6 +93,16 @@ private static void DisplayUnknownTargetError(string? target) Console.Error.WriteLine($"The target '{target}' was not recognized."); Console.ForegroundColor = originalForeground; } + + /// + /// The quantum machine submission context. + /// + private sealed class SubmissionContext : IQuantumMachineSubmissionContext + { + public string? FriendlyName { get; set; } + + public int Shots { get; set; } + } } /// diff --git a/src/Simulation/EntryPointDriver/NothingMachine.cs b/src/Simulation/EntryPointDriver/NothingMachine.cs index 167f8341585..f4bf6942e99 100644 --- a/src/Simulation/EntryPointDriver/NothingMachine.cs +++ b/src/Simulation/EntryPointDriver/NothingMachine.cs @@ -71,14 +71,14 @@ public Task SubmitAsync( EntryPointInfo info, TInput input, IQuantumMachineSubmissionContext submissionContext) => - throw new NotSupportedException(); + SubmitAsync(info, input); public Task SubmitAsync( EntryPointInfo info, TInput input, IQuantumMachineSubmissionContext submissionContext, IQuantumMachine.ConfigureJob configureJobCallback) => - throw new NotSupportedException(); + SubmitAsync(info, input); public (bool IsValid, string Message) Validate( EntryPointInfo info, TInput input) => (true, string.Empty); From 06afb5b86db10801e07d29e800efefee89dd7bb3 Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Tue, 26 May 2020 17:44:23 -0700 Subject: [PATCH 3/4] Add blank line before validation message --- src/Simulation/EntryPointDriver/Azure.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Simulation/EntryPointDriver/Azure.cs b/src/Simulation/EntryPointDriver/Azure.cs index 10c80178d9f..50a92718951 100644 --- a/src/Simulation/EntryPointDriver/Azure.cs +++ b/src/Simulation/EntryPointDriver/Azure.cs @@ -39,6 +39,7 @@ internal static async Task Submit( Console.WriteLine(isValid ? "✔️ The program is valid!" : "❌ The program is invalid."); if (!string.IsNullOrWhiteSpace(message)) { + Console.WriteLine(); Console.WriteLine(message); } return isValid ? 0 : 1; From 7406b18a9e66ab87c34b0e69eda465920b2ef56b Mon Sep 17 00:00:00 2001 From: Sarah Marshall Date: Wed, 27 May 2020 11:10:29 -0700 Subject: [PATCH 4/4] Show warning message for OutputFormat.FriendlyUri --- src/Simulation/EntryPointDriver/Azure.cs | 22 +++++++------------ src/Simulation/EntryPointDriver/Driver.cs | 20 +++++++++++++---- src/Simulation/EntryPointDriver/Simulation.cs | 6 ++--- 3 files changed, 26 insertions(+), 22 deletions(-) diff --git a/src/Simulation/EntryPointDriver/Azure.cs b/src/Simulation/EntryPointDriver/Azure.cs index 50a92718951..e5d2604c21e 100644 --- a/src/Simulation/EntryPointDriver/Azure.cs +++ b/src/Simulation/EntryPointDriver/Azure.cs @@ -6,6 +6,7 @@ using System.Threading.Tasks; using Microsoft.Azure.Quantum; using Microsoft.Quantum.Runtime; +using static Microsoft.Quantum.CsharpGeneration.EntryPointDriver.Driver; namespace Microsoft.Quantum.CsharpGeneration.EntryPointDriver { @@ -28,7 +29,8 @@ internal static async Task Submit( var machine = CreateMachine(settings); if (machine is null) { - DisplayUnknownTargetError(settings.Target); + DisplayWithColor(ConsoleColor.Red, Console.Error, + $"The target '{settings.Target}' was not recognized."); return 1; } @@ -64,7 +66,11 @@ private static void DisplayJob(IQuantumMachineJob job, OutputFormat format) switch (format) { case OutputFormat.FriendlyUri: - // TODO: Show the friendly URI. The friendly URI is not yet available from the job. + // TODO: + DisplayWithColor(ConsoleColor.Yellow, Console.Error, + "The friendly URI for viewing job results is not available yet. Showing the job ID instead."); + Console.WriteLine(job.Id); + break; case OutputFormat.Id: Console.WriteLine(job.Id); break; @@ -83,18 +89,6 @@ private static void DisplayJob(IQuantumMachineJob job, OutputFormat format) ? new NothingMachine() : QuantumMachineFactory.CreateMachine(settings.CreateWorkspace(), settings.Target, settings.Storage); - /// - /// Displays an error message for attempting to use an unknown target machine. - /// - /// The target machine. - private static void DisplayUnknownTargetError(string? target) - { - var originalForeground = Console.ForegroundColor; - Console.ForegroundColor = ConsoleColor.Red; - Console.Error.WriteLine($"The target '{target}' was not recognized."); - Console.ForegroundColor = originalForeground; - } - /// /// The quantum machine submission context. /// diff --git a/src/Simulation/EntryPointDriver/Driver.cs b/src/Simulation/EntryPointDriver/Driver.cs index 21c029dc403..38b68ebe94e 100644 --- a/src/Simulation/EntryPointDriver/Driver.cs +++ b/src/Simulation/EntryPointDriver/Driver.cs @@ -7,6 +7,7 @@ using System.CommandLine.Help; using System.CommandLine.Invocation; using System.CommandLine.Parsing; +using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -162,12 +163,9 @@ private T DefaultIfShadowed(OptionInfo option, T value) } else { - var originalForeground = Console.ForegroundColor; - Console.ForegroundColor = ConsoleColor.Yellow; - Console.Error.WriteLine( + DisplayWithColor(ConsoleColor.Yellow, Console.Error, $"Warning: Option {option.Aliases.First()} is overridden by an entry point parameter name. " + $"Using default value {option.DefaultValue}."); - Console.ForegroundColor = originalForeground; return option.DefaultValue; } } @@ -269,6 +267,20 @@ internal static class Driver new[] { "--dry-run" }, false, "Validate the program and options, but do not submit to Azure Quantum."); + + /// + /// Displays a message to the console using the given color and text writer. + /// + /// The text color. + /// The text writer for the console output stream. + /// The message to display. + internal static void DisplayWithColor(ConsoleColor color, TextWriter writer, string message) + { + var originalForeground = Console.ForegroundColor; + Console.ForegroundColor = color; + writer.WriteLine(message); + Console.ForegroundColor = originalForeground; + } } /// diff --git a/src/Simulation/EntryPointDriver/Simulation.cs b/src/Simulation/EntryPointDriver/Simulation.cs index f9d533ae0e7..a1949a07d8a 100644 --- a/src/Simulation/EntryPointDriver/Simulation.cs +++ b/src/Simulation/EntryPointDriver/Simulation.cs @@ -7,6 +7,7 @@ using Microsoft.Quantum.QsCompiler.ReservedKeywords; using Microsoft.Quantum.Simulation.Core; using Microsoft.Quantum.Simulation.Simulators; +using static Microsoft.Quantum.CsharpGeneration.EntryPointDriver.Driver; namespace Microsoft.Quantum.CsharpGeneration.EntryPointDriver { @@ -85,10 +86,7 @@ private static async Task RunSimulator( /// The name of the custom simulator. private static void DisplayCustomSimulatorError(string name) { - var originalForeground = Console.ForegroundColor; - Console.ForegroundColor = ConsoleColor.Red; - Console.Error.WriteLine($"The simulator '{name}' could not be found."); - Console.ForegroundColor = originalForeground; + DisplayWithColor(ConsoleColor.Red, Console.Error, $"The simulator '{name}' could not be found."); Console.Error.WriteLine(); Console.Error.WriteLine( $"If '{name}' is a custom simulator, it must be set in the DefaultSimulator project property:");