Skip to content
This repository was archived by the owner on Jan 12, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 47 additions & 16 deletions src/Simulation/EntryPointDriver/Azure.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand All @@ -28,27 +29,54 @@ internal static async Task<int> Submit<TIn, TOut>(
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;
}

// 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)
{
case OutputFormat.FriendlyUri:
Console.WriteLine("Job submitted. To track your job status and see the results use:");
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();
// TODO: Show the friendly URI. The friendly URI is not yet available from the job.
Console.WriteLine(message);
}
return isValid ? 0 : 1;
}
else
{
var job = await machine.SubmitAsync(
entryPoint.Info, input, new SubmissionContext { Shots = settings.Shots });
DisplayJob(job, settings.Output);
return 0;
}
}

/// <summary>
/// Displays the job using the output format.
/// </summary>
/// <param name="job">The job.</param>
/// <param name="format">The output format.</param>
/// <exception cref="ArgumentOutOfRangeException">Thrown if the output format is invalid.</exception>
private static void DisplayJob(IQuantumMachineJob job, OutputFormat format)
{
switch (format)
{
case OutputFormat.FriendlyUri:
// 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;
default:
throw new ArgumentOutOfRangeException($"Invalid output format '{settings.Output}'.");
throw new ArgumentOutOfRangeException($"Invalid output format '{format}'.");
}
return 0;
}

/// <summary>
Expand All @@ -62,15 +90,13 @@ internal static async Task<int> Submit<TIn, TOut>(
: QuantumMachineFactory.CreateMachine(settings.CreateWorkspace(), settings.Target, settings.Storage);

/// <summary>
/// Displays an error message for attempting to use an unknown target machine.
/// The quantum machine submission context.
/// </summary>
/// <param name="target">The target machine.</param>
private static void DisplayUnknownTargetError(string? target)
private sealed class SubmissionContext : IQuantumMachineSubmissionContext
{
var originalForeground = Console.ForegroundColor;
Console.ForegroundColor = ConsoleColor.Red;
Console.Error.WriteLine($"The target '{target}' was not recognized.");
Console.ForegroundColor = originalForeground;
public string? FriendlyName { get; set; }

public int Shots { get; set; }
}
}

Expand Down Expand Up @@ -140,6 +166,11 @@ internal sealed class AzureSettings
/// </summary>
public OutputFormat Output { get; set; }

/// <summary>
/// Validate the program and options, but do not submit to Azure Quantum.
/// </summary>
public bool DryRun { get; set; }

/// <summary>
/// Creates a <see cref="Workspace"/> based on the settings.
/// </summary>
Expand Down
36 changes: 30 additions & 6 deletions src/Simulation/EntryPointDriver/Driver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
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;
using Microsoft.Quantum.QsCompiler.ReservedKeywords;
using Microsoft.Quantum.Simulation.Core;
Expand Down Expand Up @@ -84,6 +86,7 @@ public async Task<int> 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)
Expand All @@ -98,6 +101,7 @@ public async Task<int> Run(string[] args)
}
root.Handler = simulate.Handler;

Console.OutputEncoding = Encoding.UTF8;
return await new CommandLineBuilder(root)
.UseDefaults()
.UseHelpBuilder(context => new QsHelpBuilder(context.Console))
Expand Down Expand Up @@ -131,9 +135,10 @@ private async Task<int> 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)
});

/// <summary>
/// Returns true if the alias is not already used by an entry point option.
/// </summary>
Expand All @@ -158,12 +163,9 @@ private T DefaultIfShadowed<T>(OptionInfo<T> 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;
}
}
Expand Down Expand Up @@ -257,6 +259,28 @@ internal static class Driver
new[] { "--output" },
OutputFormat.FriendlyUri,
"The information to show in the output after the job is submitted.");

/// <summary>
/// The dry run option.
/// </summary>
internal static readonly OptionInfo<bool> DryRunOption = new OptionInfo<bool>(
new[] { "--dry-run" },
false,
"Validate the program and options, but do not submit to Azure Quantum.");

/// <summary>
/// Displays a message to the console using the given color and text writer.
/// </summary>
/// <param name="color">The text color.</param>
/// <param name="writer">The text writer for the console output stream.</param>
/// <param name="message">The message to display.</param>
internal static void DisplayWithColor(ConsoleColor color, TextWriter writer, string message)
{
var originalForeground = Console.ForegroundColor;
Console.ForegroundColor = color;
writer.WriteLine(message);
Console.ForegroundColor = originalForeground;
}
}

/// <summary>
Expand Down
13 changes: 6 additions & 7 deletions src/Simulation/EntryPointDriver/NothingMachine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ namespace Microsoft.Quantum.CsharpGeneration.EntryPointDriver
/// </summary>
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<IQuantumMachineOutput<TOutput>> ExecuteAsync<TInput, TOutput>(
EntryPointInfo<TInput, TOutput> info, TInput input) =>
Expand Down Expand Up @@ -71,18 +71,17 @@ public Task<IQuantumMachineJob> SubmitAsync<TInput, TOutput>(
EntryPointInfo<TInput, TOutput> info,
TInput input,
IQuantumMachineSubmissionContext submissionContext) =>
throw new NotSupportedException();
SubmitAsync(info, input);

public Task<IQuantumMachineJob> SubmitAsync<TInput, TOutput>(
EntryPointInfo<TInput, TOutput> info,
TInput input,
IQuantumMachineSubmissionContext submissionContext,
IQuantumMachine.ConfigureJob configureJobCallback) =>
throw new NotSupportedException();
SubmitAsync(info, input);

public (bool IsValid, string Message) Validate<TInput, TOutput>(
EntryPointInfo<TInput, TOutput> info, TInput input) =>
throw new NotSupportedException();
EntryPointInfo<TInput, TOutput> info, TInput input) => (true, string.Empty);

/// <summary>
/// A quantum machine job with default properties.
Expand All @@ -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();

Expand Down
6 changes: 2 additions & 4 deletions src/Simulation/EntryPointDriver/Simulation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down Expand Up @@ -85,10 +86,7 @@ private static async Task RunSimulator(
/// <param name="name">The name of the custom simulator.</param>
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:");
Expand Down