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
21 changes: 14 additions & 7 deletions src/Simulation/CsharpGeneration/EntryPoint.fs
Original file line number Diff line number Diff line change
Expand Up @@ -133,21 +133,28 @@ let private mainMethod context entryPoint =
let private entryPointClass context entryPoint =
let callableName, argTypeName, returnTypeName = callableTypeNames context entryPoint
let property name typeName value = ``property-arrow_get`` typeName name [``public``] get (``=>`` value)
let summaryProperty = property "Summary" "string" (literal ((PrintSummary entryPoint.Documentation false).Trim ()))
let summaryProperty =
(PrintSummary entryPoint.Documentation false).Trim ()
|> literal
|> property "Summary" "string"
let parameters = parameters context entryPoint.Documentation entryPoint.ArgumentTuple
let defaultSimulator =
context.assemblyConstants.TryGetValue AssemblyConstants.DefaultSimulator
|> snd
|> (fun value -> if String.IsNullOrWhiteSpace value then AssemblyConstants.QuantumSimulator else value)
let defaultSimulatorNameProperty = property "DefaultSimulatorName" "string" (literal defaultSimulator)
|> fun (_, value) -> if String.IsNullOrWhiteSpace value then AssemblyConstants.QuantumSimulator else value
let defaultSimulatorNameProperty = literal defaultSimulator |> property "DefaultSimulatorName" "string"
let defaultExecutionTargetProperty =
context.assemblyConstants.TryGetValue AssemblyConstants.ExecutionTarget
|> (fun (_, value) -> if value = null then "" else value)
|> literal
|> property "DefaultExecutionTarget" "string"
let infoProperty =
property "Info"
(sprintf "EntryPointInfo<%s, %s>" argTypeName returnTypeName)
(ident callableName <|.|> ident "Info")
property "Info" (sprintf "EntryPointInfo<%s, %s>" argTypeName returnTypeName)
(ident callableName <|.|> ident "Info")
let members : MemberDeclarationSyntax list = [
summaryProperty
parameterOptionsProperty parameters
defaultSimulatorNameProperty
defaultExecutionTargetProperty
infoProperty
customSimulatorFactory defaultSimulator
createArgument context entryPoint
Expand Down
128 changes: 106 additions & 22 deletions src/Simulation/EntryPointDriver.Tests/Tests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
module Microsoft.Quantum.EntryPointDriver.Tests

open System
open System.Collections.Generic
open System.Collections.Immutable
open System.Globalization
open System.IO
Expand Down Expand Up @@ -59,14 +60,9 @@ let private compileQsharp source =
Assert.Empty errors
compilation.BuiltCompilation

/// Generates C# source code from the compiled Q# syntax tree. The given default simulator is set as an assembly
/// constant.
let private generateCsharp defaultSimulator (compilation : QsCompilation) =
let assemblyConstants =
match defaultSimulator with
| Some simulator -> ImmutableDictionary.Empty.Add (AssemblyConstants.DefaultSimulator, simulator)
| None -> ImmutableDictionary.Empty
let context = CodegenContext.Create (compilation, assemblyConstants)
/// Generates C# source code from the compiled Q# syntax tree using the given assembly constants.
let private generateCsharp constants (compilation : QsCompilation) =
let context = CodegenContext.Create (compilation, constants)
let entryPoint = context.allCallables.[Seq.exactlyOne compilation.EntryPoints]
[
SimulationCode.generate (NonNullable<_>.New testFile) context
Expand Down Expand Up @@ -112,12 +108,12 @@ let private compileCsharp (sources : string seq) =
Assert.Equal (0L, stream.Seek (0L, SeekOrigin.Begin))
Assembly.Load (stream.ToArray ())

/// The assembly for the given test case and default simulator.
let private testAssembly testNum defaultSimulator =
/// The assembly for the given test case assembly constants.
let private testAssembly testNum constants =
testNum
|> testCase
|> compileQsharp
|> generateCsharp defaultSimulator
|> generateCsharp constants
|> compileCsharp

/// Runs the entry point in the assembly with the given command-line arguments, and returns the output, errors, and exit
Expand Down Expand Up @@ -164,17 +160,26 @@ let private failsWith expected (assembly, args) =
Assert.True (0 <> exitCode, sprintf "Expected non-zero exit code, but got 0 with:\n\n%s\n\n%s" error out)
Assert.StartsWith (normalize expected, normalize (error + out))

/// A tuple of the test assembly and arguments using the standard default simulator. The tuple can be passed to yields
/// or fails.
let private test testNum =
let assembly = testAssembly testNum None
/// A tuple of the test assembly and arguments using the given assembly constants. The tuple can be passed to yields or
/// fails.
let private testWithConstants constants testNum =
let assembly = testAssembly testNum constants
fun args -> assembly, Array.ofList args

/// A tuple of the test assembly and arguments with no assembly constants. The tuple can be passed to yields or fails.
let private test = testWithConstants ImmutableDictionary.Empty

/// A tuple of the test assembly and arguments using the given default simulator. The tuple can be passed to yields or
/// fails.
let private testWith testNum defaultSimulator =
let assembly = testAssembly testNum (Some defaultSimulator)
fun args -> assembly, Array.ofList args
let private testWithSim defaultSimulator =
ImmutableDictionary.CreateRange [KeyValuePair (AssemblyConstants.DefaultSimulator, defaultSimulator)]
|> testWithConstants

/// A tuple of the test assembly and arguments using the given default target. The tuple can be passed to yields or
/// fails.
let private testWithTarget defaultTarget =
ImmutableDictionary.CreateRange [KeyValuePair (AssemblyConstants.ExecutionTarget, defaultTarget)]
|> testWithConstants

/// Standard command-line arguments for the "submit" command without specifying a target.
let private submitWithoutTarget =
Expand Down Expand Up @@ -509,15 +514,15 @@ let ``Rejects unknown simulator`` () =

[<Fact>]
let ``Supports default standard simulator`` () =
let given = testWith 32 AssemblyConstants.ResourcesEstimator
let given = testWithSim AssemblyConstants.ResourcesEstimator 32
given ["--use-h"; "false"] |> yields resourceSummary
given ["--simulator"; AssemblyConstants.QuantumSimulator; "--use-h"; "false"] |> yields "Hello, World!"

[<Fact>]
let ``Supports default custom simulator`` () =
// This is not really a "custom" simulator, but the driver does not recognize the fully-qualified name of the
// standard simulators, so it is treated as one.
let given = testWith 32 typeof<ToffoliSimulator>.FullName
let given = testWithSim typeof<ToffoliSimulator>.FullName 32
given ["--use-h"; "false"] |> yields "Hello, World!"
given ["--use-h"; "true"] |> fails
given ["--simulator"; typeof<ToffoliSimulator>.FullName; "--use-h"; "false"] |> yields "Hello, World!"
Expand Down Expand Up @@ -547,10 +552,30 @@ let ``Submit uses default values`` () =
let given = test 1
given (submitWithNothingTarget @ ["--verbose"])
|> yields "The friendly URI for viewing job results is not available yet. Showing the job ID instead.
Subscription: mySubscription
Resource Group: myResourceGroup
Workspace: myWorkspace
Target: test.nothing
Storage:
AAD Token:
Base URI:
Job Name:
Shots: 500
Output: FriendlyUri
Dry Run: False
Verbose: True

00000000-0000-0000-0000-0000000000000"

[<Fact>]
let ``Submit uses default values with default target`` () =
let given = testWithTarget "test.nothing" 1
given (submitWithoutTarget @ ["--verbose"])
|> yields "The friendly URI for viewing job results is not available yet. Showing the job ID instead.
Subscription: mySubscription
Resource Group: myResourceGroup
Workspace: myWorkspace
Target: test.nothing
Storage:
AAD Token:
Base URI:
Expand Down Expand Up @@ -579,10 +604,42 @@ let ``Submit allows overriding default values`` () =
"750"
])
|> yields "The friendly URI for viewing job results is not available yet. Showing the job ID instead.
Subscription: mySubscription
Resource Group: myResourceGroup
Workspace: myWorkspace
Target: test.nothing
Storage: myStorage
AAD Token: myToken
Base URI: myBaseUri
Job Name: myJobName
Shots: 750
Output: FriendlyUri
Dry Run: False
Verbose: True

00000000-0000-0000-0000-0000000000000"

[<Fact>]
let ``Submit allows overriding default values with default target`` () =
let given = testWithTarget "foo.target" 1
given (submitWithNothingTarget @ [
"--verbose"
"--storage"
"myStorage"
"--aad-token"
"myToken"
"--base-uri"
"myBaseUri"
"--job-name"
"myJobName"
"--shots"
"750"
])
|> yields "The friendly URI for viewing job results is not available yet. Showing the job ID instead.
Subscription: mySubscription
Resource Group: myResourceGroup
Workspace: myWorkspace
Target: test.nothing
Storage: myStorage
AAD Token: myToken
Base URI: myBaseUri
Expand Down Expand Up @@ -685,10 +742,10 @@ let ``Shows help text for submit command`` () =
%s submit [options]

Options:
--target <target> (REQUIRED) The target device ID.
--subscription <subscription> (REQUIRED) The subscription ID.
--resource-group <resource-group> (REQUIRED) The resource group name.
--workspace <workspace> (REQUIRED) The workspace name.
--target <target> (REQUIRED) The target device ID.
--storage <storage> The storage account connection string.
--aad-token <aad-token> The Azure Active Directory authentication token.
--base-uri <base-uri> The base URI of the Azure Quantum endpoint.
Expand All @@ -701,6 +758,33 @@ let ``Shows help text for submit command`` () =
--pauli <PauliI|PauliX|PauliY|PauliZ> (REQUIRED) The name of a Pauli matrix.
--my-cool-bool (REQUIRED) A neat bit.
-?, -h, --help Show help and usage information"

let given = test 33
given ["submit"; "--help"] |> yields message

[<Fact>]
let ``Shows help text for submit command with default target`` () =
let name = Path.GetFileNameWithoutExtension (Assembly.GetEntryAssembly().Location)
let message =
name
|> sprintf "Usage:
%s submit [options]

Options:
--subscription <subscription> (REQUIRED) The subscription ID.
--resource-group <resource-group> (REQUIRED) The resource group name.
--workspace <workspace> (REQUIRED) The workspace name.
--target <target> The target device ID.
--storage <storage> The storage account connection string.
--aad-token <aad-token> The Azure Active Directory authentication token.
--base-uri <base-uri> The base URI of the Azure Quantum endpoint.
--job-name <job-name> The name of the submitted job.
--shots <shots> The number of times the program is executed on the target machine.
--output <FriendlyUri|Id> The information to show in the output after the job is submitted.
--dry-run Validate the program and options, but do not submit to Azure Quantum.
--verbose Show additional information about the submission.
-n <n> (REQUIRED) A number.
--pauli <PauliI|PauliX|PauliY|PauliZ> (REQUIRED) The name of a Pauli matrix.
--my-cool-bool (REQUIRED) A neat bit.
-?, -h, --help Show help and usage information"
let given = testWithTarget "foo.target" 33
given ["submit"; "--help"] |> yields message
14 changes: 8 additions & 6 deletions src/Simulation/EntryPointDriver/Azure.cs
Original file line number Diff line number Diff line change
Expand Up @@ -150,9 +150,11 @@ private static void DisplayError(string summary, string message)
/// Creates a quantum machine based on the Azure Quantum submission settings.
/// </summary>
/// <param name="settings">The Azure Quantum submission settings.</param>
/// <exception cref="ArgumentNullException">Thrown if <paramref name="settings"/>.Target is null.</exception>
/// <returns>A quantum machine.</returns>
private static IQuantumMachine? CreateMachine(AzureSettings settings) => settings.Target switch
{
null => throw new ArgumentNullException(nameof(settings), "Target is null."),
NothingMachine.TargetId => new NothingMachine(),
ErrorMachine.TargetId => new ErrorMachine(),
_ => QuantumMachineFactory.CreateMachine(settings.CreateWorkspace(), settings.Target, settings.Storage)
Expand Down Expand Up @@ -190,11 +192,6 @@ internal enum OutputFormat
/// </summary>
internal sealed class AzureSettings
{
/// <summary>
/// The target device ID.
/// </summary>
public string? Target { get; set; }

/// <summary>
/// The subscription ID.
/// </summary>
Expand All @@ -210,6 +207,11 @@ internal sealed class AzureSettings
/// </summary>
public string? Workspace { get; set; }

/// <summary>
/// The target device ID.
/// </summary>
public string? Target { get; set; }

/// <summary>
/// The storage account connection string.
/// </summary>
Expand Down Expand Up @@ -261,10 +263,10 @@ AadToken is null

public override string ToString() =>
string.Join(System.Environment.NewLine,
$"Target: {Target}",
$"Subscription: {Subscription}",
$"Resource Group: {ResourceGroup}",
$"Workspace: {Workspace}",
$"Target: {Target}",
$"Storage: {Storage}",
$"AAD Token: {AadToken}",
$"Base URI: {BaseUri}",
Expand Down
22 changes: 14 additions & 8 deletions src/Simulation/EntryPointDriver/Driver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ public sealed class Driver<TCallable, TIn, TOut> where TCallable : AbstractCalla
/// </summary>
private OptionInfo<string> SimulatorOption { get; }

/// <summary>
/// The target option.
/// </summary>
private OptionInfo<string?> TargetOption { get; }

/// <summary>
/// Creates a new driver for the entry point.
/// </summary>
Expand All @@ -49,6 +54,7 @@ public Driver(DriverSettings settings, IEntryPoint<TIn, TOut> entryPoint)
{
this.settings = settings;
this.entryPoint = entryPoint;

SimulatorOption = new OptionInfo<string>(
settings.SimulatorOptionAliases,
entryPoint.DefaultSimulatorName,
Expand All @@ -60,6 +66,12 @@ public Driver(DriverSettings settings, IEntryPoint<TIn, TOut> entryPoint)
settings.ResourcesEstimatorName,
entryPoint.DefaultSimulatorName
});

var targetAliases = ImmutableList.Create("--target");
const string targetDescription = "The target device ID.";
TargetOption = string.IsNullOrWhiteSpace(entryPoint.DefaultExecutionTarget)
? new OptionInfo<string?>(targetAliases, targetDescription)
: new OptionInfo<string?>(targetAliases, entryPoint.DefaultExecutionTarget, targetDescription);
}

/// <summary>
Expand All @@ -80,10 +92,10 @@ public async Task<int> Run(string[] args)
IsHidden = true,
Handler = CommandHandler.Create<ParseResult, AzureSettings>(Submit)
};
AddOptionIfAvailable(submit, TargetOption);
AddOptionIfAvailable(submit, SubscriptionOption);
AddOptionIfAvailable(submit, ResourceGroupOption);
AddOptionIfAvailable(submit, WorkspaceOption);
AddOptionIfAvailable(submit, TargetOption);
AddOptionIfAvailable(submit, StorageOption);
AddOptionIfAvailable(submit, AadTokenOption);
AddOptionIfAvailable(submit, BaseUriOption);
Expand Down Expand Up @@ -132,10 +144,10 @@ await Simulation<TCallable, TIn, TOut>.Simulate(
private async Task<int> Submit(ParseResult parseResult, AzureSettings azureSettings) =>
await Azure.Submit(entryPoint, parseResult, new AzureSettings
{
Target = azureSettings.Target,
Subscription = azureSettings.Subscription,
ResourceGroup = azureSettings.ResourceGroup,
Workspace = azureSettings.Workspace,
Target = DefaultIfShadowed(TargetOption, azureSettings.Target),
Storage = DefaultIfShadowed(StorageOption, azureSettings.Storage),
AadToken = DefaultIfShadowed(AadTokenOption, azureSettings.AadToken),
BaseUri = DefaultIfShadowed(BaseUriOption, azureSettings.BaseUri),
Expand Down Expand Up @@ -205,12 +217,6 @@ internal static class Driver
{
// TODO: Define the aliases as constants.

/// <summary>
/// The target option.
/// </summary>
internal static readonly OptionInfo<string> TargetOption = new OptionInfo<string>(
ImmutableList.Create("--target"), "The target device ID.");

/// <summary>
/// The subscription option.
/// </summary>
Expand Down
2 changes: 1 addition & 1 deletion src/Simulation/EntryPointDriver/DriverSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace Microsoft.Quantum.EntryPointDriver
{
/// <summary>
/// Settings for the entry point driver.
/// General settings for the entry point driver that do not depend on the entry point or compilation target.
/// </summary>
public sealed class DriverSettings
{
Expand Down
5 changes: 5 additions & 0 deletions src/Simulation/EntryPointDriver/IEntryPoint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ public interface IEntryPoint<TIn, TOut>
/// </summary>
string DefaultSimulatorName { get; }

/// <summary>
/// The default execution target when to use when submitting the entry point to Azure Quantum.
/// </summary>
string DefaultExecutionTarget { get; }

/// <summary>
/// Additional information about the entry point.
/// </summary>
Expand Down