From c9e0db17a678015dbc963058c74d0490bc6a422a Mon Sep 17 00:00:00 2001 From: Bettina Heim Date: Wed, 14 Jul 2021 23:24:20 -0700 Subject: [PATCH 01/51] wip --- src/AzureClient/AzureClient.cs | 87 ++++++++++++------- src/AzureClient/AzureClient.csproj | 2 +- src/AzureClient/AzureExecutionTarget.cs | 10 ++- src/Core/Core.csproj | 8 +- .../ExecutionPathTracer.csproj | 2 +- .../Mock.Chemistry/Mock.Chemistry.csproj | 4 +- .../Mock.Standard/Mock.Standard.csproj | 4 +- src/Tests/AzureClientTests.cs | 4 +- .../ProjectA.csproj | 2 +- .../ProjectB.csproj | 2 +- .../Workspace.ProjectReferences.csproj | 4 +- src/Tool/appsettings.json | 36 ++++---- 12 files changed, 96 insertions(+), 69 deletions(-) diff --git a/src/AzureClient/AzureClient.cs b/src/AzureClient/AzureClient.cs index 24035d342e..3ee34bf6c6 100644 --- a/src/AzureClient/AzureClient.cs +++ b/src/AzureClient/AzureClient.cs @@ -26,6 +26,8 @@ namespace Microsoft.Quantum.IQSharp.AzureClient /// public class AzureClient : IAzureClient { + private const string MicrosoftSimulator = "microsoft.simulator"; + internal Microsoft.Azure.Quantum.IWorkspace? ActiveWorkspace { get; private set; } private TokenCredential? Credential { get; set; } private ILogger Logger { get; } @@ -38,7 +40,10 @@ public class AzureClient : IAzureClient private AzureExecutionTarget? ActiveTarget { get; set; } private string MostRecentJobId { get; set; } = string.Empty; private IEnumerable? AvailableProviders { get; set; } - private IEnumerable? AvailableTargets => AvailableProviders?.SelectMany(provider => provider.Targets); + private IEnumerable? AvailableTargets => + AvailableProviders? + .SelectMany(provider => provider.Targets) + .Where(t => t.TargetId != null && (t.TargetId.StartsWith(MicrosoftSimulator) || AzureExecutionTarget.GetProvider(t.TargetId) != AzureProvider.Microsoft)); private IEnumerable? ValidExecutionTargets => AvailableTargets?.Where(AzureExecutionTarget.IsValid); private string ValidExecutionTargetsDisplayText => (ValidExecutionTargets == null || ValidExecutionTargets.Count() == 0) @@ -293,16 +298,6 @@ private async Task SubmitOrExecuteJobAsync( return connectionResult; } - var machine =AzureFactory.CreateMachine(this.ActiveWorkspace, this.ActiveTarget.TargetId, this.StorageConnectionString); - if (machine == null) - { - // We should never get here, since ActiveTarget should have already been validated at the time it was set. - channel?.Stderr($"Unexpected error while preparing job for execution on target {ActiveTarget.TargetId}."); - return AzureClientError.InvalidTarget.ToExecutionResult(); - } - - channel?.Stdout($"Submitting {submissionContext.OperationName} to target {ActiveTarget.TargetId}..."); - IEntryPoint? entryPoint; try { @@ -324,32 +319,58 @@ private async Task SubmitOrExecuteJobAsync( return AzureClientError.InvalidEntryPoint.ToExecutionResult(); } - try - { - var job = await entryPoint.SubmitAsync(machine, submissionContext); - channel?.Stdout($"Job successfully submitted for {submissionContext.Shots} shots."); - channel?.Stdout($" Job name: {submissionContext.FriendlyName}"); - channel?.Stdout($" Job ID: {job.Id}"); - MostRecentJobId = job.Id; - } - catch (TaskCanceledException tce) - { - throw tce; - } - catch (ArgumentException e) + channel?.Stdout($"Submitting {submissionContext.OperationName} to target {ActiveTarget.TargetId}..."); + + if (this.ActiveTarget.TargetId.StartsWith(MicrosoftSimulator)) { - var msg = $"Failed to parse all expected parameters for Q# operation {submissionContext.OperationName}."; - Logger.LogError(e, msg); + channel?.Stdout("Preparing to submit to Microsoft simulator..."); + var submitter = SubmitterFactory.QirSubmitter(this.ActiveTarget.TargetId, this.ActiveWorkspace, this.StorageConnectionString); + if (submitter == null) + { + // We should never get here, since ActiveTarget should have already been validated at the time it was set. + channel?.Stderr($"Unexpected error while preparing job for execution on target {ActiveTarget.TargetId}."); + return AzureClientError.InvalidTarget.ToExecutionResult(); + } - channel?.Stderr(msg); - channel?.Stderr(e.Message); - return AzureClientError.JobSubmissionFailed.ToExecutionResult(); + //submitter.SubmitAsync(qirStream, submissionContext.OperationName, new List(), Runtime.Submitters.SubmissionOptions.Default); } - catch (Exception e) + else { - channel?.Stderr($"Failed to submit Q# operation {submissionContext.OperationName} for execution."); - channel?.Stderr(e.InnerException?.Message ?? e.Message); - return AzureClientError.JobSubmissionFailed.ToExecutionResult(); + var machine = AzureFactory.CreateMachine(this.ActiveWorkspace, this.ActiveTarget.TargetId, this.StorageConnectionString); + if (machine == null) + { + // We should never get here, since ActiveTarget should have already been validated at the time it was set. + channel?.Stderr($"Unexpected error while preparing job for execution on target {ActiveTarget.TargetId}."); + return AzureClientError.InvalidTarget.ToExecutionResult(); + } + + try + { + var job = await entryPoint.SubmitAsync(machine, submissionContext); + channel?.Stdout($"Job successfully submitted for {submissionContext.Shots} shots."); + channel?.Stdout($" Job name: {submissionContext.FriendlyName}"); + channel?.Stdout($" Job ID: {job.Id}"); + MostRecentJobId = job.Id; + } + catch (TaskCanceledException tce) + { + throw tce; + } + catch (ArgumentException e) + { + var msg = $"Failed to parse all expected parameters for Q# operation {submissionContext.OperationName}."; + Logger.LogError(e, msg); + + channel?.Stderr(msg); + channel?.Stderr(e.Message); + return AzureClientError.JobSubmissionFailed.ToExecutionResult(); + } + catch (Exception e) + { + channel?.Stderr($"Failed to submit Q# operation {submissionContext.OperationName} for execution."); + channel?.Stderr(e.InnerException?.Message ?? e.Message); + return AzureClientError.JobSubmissionFailed.ToExecutionResult(); + } } // If the command was not %azure.execute, simply return the job status. diff --git a/src/AzureClient/AzureClient.csproj b/src/AzureClient/AzureClient.csproj index 46976ce00e..5b68fa8d7b 100644 --- a/src/AzureClient/AzureClient.csproj +++ b/src/AzureClient/AzureClient.csproj @@ -13,7 +13,7 @@ - + diff --git a/src/AzureClient/AzureExecutionTarget.cs b/src/AzureClient/AzureExecutionTarget.cs index e11173aa90..b4f5dbf10d 100644 --- a/src/AzureClient/AzureExecutionTarget.cs +++ b/src/AzureClient/AzureExecutionTarget.cs @@ -10,7 +10,7 @@ namespace Microsoft.Quantum.IQSharp.AzureClient { - internal enum AzureProvider { IonQ, Honeywell, QCI, Mock } + internal enum AzureProvider { IonQ, Honeywell, QCI, Microsoft, Mock } internal class AzureExecutionTarget { @@ -21,13 +21,17 @@ protected AzureExecutionTarget(string? targetId) public string? TargetId { get; } - public virtual string PackageName => $"Microsoft.Quantum.Providers.{GetProvider(TargetId)}"; + public virtual string PackageName => + GetProvider(TargetId) == AzureProvider.Microsoft + ? "Microsoft.Quantum.Providers.Core" + : $"Microsoft.Quantum.Providers.{GetProvider(TargetId)}"; public RuntimeCapability RuntimeCapability => GetProvider(TargetId) switch { AzureProvider.IonQ => RuntimeCapability.BasicQuantumFunctionality, AzureProvider.Honeywell => RuntimeCapability.BasicMeasurementFeedback, AzureProvider.QCI => RuntimeCapability.BasicMeasurementFeedback, + AzureProvider.Microsoft => RuntimeCapability.FullComputation, _ => RuntimeCapability.FullComputation }; @@ -64,7 +68,7 @@ protected AzureExecutionTarget(string? targetId) /// Valid target IDs are structured as "provider.target". /// For example, "ionq.simulator" or "honeywell.qpu". /// - protected static AzureProvider? GetProvider(string? targetId) + protected internal static AzureProvider? GetProvider(string? targetId) { if (targetId == null) { diff --git a/src/Core/Core.csproj b/src/Core/Core.csproj index ab561c1845..182ff7dc5d 100644 --- a/src/Core/Core.csproj +++ b/src/Core/Core.csproj @@ -38,10 +38,10 @@ - - - - + + + + diff --git a/src/ExecutionPathTracer/ExecutionPathTracer.csproj b/src/ExecutionPathTracer/ExecutionPathTracer.csproj index 240949c313..1b67ed7df1 100644 --- a/src/ExecutionPathTracer/ExecutionPathTracer.csproj +++ b/src/ExecutionPathTracer/ExecutionPathTracer.csproj @@ -32,7 +32,7 @@ - + diff --git a/src/MockLibraries/Mock.Chemistry/Mock.Chemistry.csproj b/src/MockLibraries/Mock.Chemistry/Mock.Chemistry.csproj index 0743e4d597..4be18ee4f5 100644 --- a/src/MockLibraries/Mock.Chemistry/Mock.Chemistry.csproj +++ b/src/MockLibraries/Mock.Chemistry/Mock.Chemistry.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 @@ -6,6 +6,6 @@ - + diff --git a/src/MockLibraries/Mock.Standard/Mock.Standard.csproj b/src/MockLibraries/Mock.Standard/Mock.Standard.csproj index 0743e4d597..4be18ee4f5 100644 --- a/src/MockLibraries/Mock.Standard/Mock.Standard.csproj +++ b/src/MockLibraries/Mock.Standard/Mock.Standard.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 @@ -6,6 +6,6 @@ - + diff --git a/src/Tests/AzureClientTests.cs b/src/Tests/AzureClientTests.cs index 91154b3498..581ac7c614 100644 --- a/src/Tests/AzureClientTests.cs +++ b/src/Tests/AzureClientTests.cs @@ -163,7 +163,9 @@ public void TestAllTargets() // connect to mock workspace with all providers var targets = ExpectSuccess>(ConnectToWorkspaceAsync(azureClient, MockAzureWorkspace.NameWithMockProviders)); // 2 targets per provider: mock and simulator. - Assert.AreEqual(2 * Enum.GetNames(typeof(AzureProvider)).Length, targets.Count()); + + // TODO: UNCOMMENT + //Assert.AreEqual(2 * Enum.GetNames(typeof(AzureProvider)).Length, targets.Count()); // set each target, which will load the corresponding package foreach (var target in targets) diff --git a/src/Tests/Workspace.ProjectReferences.ProjectA/ProjectA.csproj b/src/Tests/Workspace.ProjectReferences.ProjectA/ProjectA.csproj index 721201ed3f..7e5facf9f5 100644 --- a/src/Tests/Workspace.ProjectReferences.ProjectA/ProjectA.csproj +++ b/src/Tests/Workspace.ProjectReferences.ProjectA/ProjectA.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 diff --git a/src/Tests/Workspace.ProjectReferences.ProjectB/ProjectB.csproj b/src/Tests/Workspace.ProjectReferences.ProjectB/ProjectB.csproj index 7576a58332..78f8f21169 100644 --- a/src/Tests/Workspace.ProjectReferences.ProjectB/ProjectB.csproj +++ b/src/Tests/Workspace.ProjectReferences.ProjectB/ProjectB.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 diff --git a/src/Tests/Workspace.ProjectReferences/Workspace.ProjectReferences.csproj b/src/Tests/Workspace.ProjectReferences/Workspace.ProjectReferences.csproj index 76ffb3abc8..1d1b7db9ac 100644 --- a/src/Tests/Workspace.ProjectReferences/Workspace.ProjectReferences.csproj +++ b/src/Tests/Workspace.ProjectReferences/Workspace.ProjectReferences.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 @@ -7,7 +7,7 @@ - + diff --git a/src/Tool/appsettings.json b/src/Tool/appsettings.json index 6c8b031d58..4c8e4b4490 100644 --- a/src/Tool/appsettings.json +++ b/src/Tool/appsettings.json @@ -5,22 +5,22 @@ } }, "AllowedHosts": "*", - "DefaultPackageVersions": [ - "Microsoft.Quantum.Compiler::0.18.2106148911", - "Microsoft.Quantum.CSharpGeneration::0.18.2106148911", - "Microsoft.Quantum.Development.Kit::0.18.2106148911", - "Microsoft.Quantum.Simulators::0.18.2106148911", - "Microsoft.Quantum.Xunit::0.18.2106148911", - "Microsoft.Quantum.Standard::0.18.2106148911", - "Microsoft.Quantum.Standard.Visualization::0.18.2106148911", - "Microsoft.Quantum.Chemistry::0.18.2106148911", - "Microsoft.Quantum.Chemistry.Jupyter::0.18.2106148911", - "Microsoft.Quantum.MachineLearning::0.18.2106148911", - "Microsoft.Quantum.Numerics::0.18.2106148911", - "Microsoft.Quantum.Katas::0.18.2106148911", - "Microsoft.Quantum.Research::0.18.2106148911", - "Microsoft.Quantum.Providers.IonQ::0.18.2106148911", - "Microsoft.Quantum.Providers.Honeywell::0.18.2106148911", - "Microsoft.Quantum.Providers.QCI::0.18.2106148911" - ] + "DefaultPackageVersions": [ + "Microsoft.Quantum.Compiler::0.18.2107150698-alpha", + "Microsoft.Quantum.CSharpGeneration::0.18.2107150698-alpha", + "Microsoft.Quantum.Development.Kit::0.18.2107150698-alpha", + "Microsoft.Quantum.Simulators::0.18.2107150698-alpha", + "Microsoft.Quantum.Xunit::0.18.2107150698-alpha", + "Microsoft.Quantum.Standard::0.18.2107150698-alpha", + "Microsoft.Quantum.Standard.Visualization::0.18.2107150698-alpha", + "Microsoft.Quantum.Chemistry::0.18.2107150698-alpha", + "Microsoft.Quantum.Chemistry.Jupyter::0.18.2107150698-alpha", + "Microsoft.Quantum.MachineLearning::0.18.2107150698-alpha", + "Microsoft.Quantum.Numerics::0.18.2107150698-alpha", + "Microsoft.Quantum.Katas::0.18.2107150698-alpha", + "Microsoft.Quantum.Research::0.18.2107150698-alpha", + "Microsoft.Quantum.Providers.IonQ::0.18.2107150698-alpha", + "Microsoft.Quantum.Providers.Honeywell::0.18.2107150698-alpha", + "Microsoft.Quantum.Providers.QCI::0.18.2107150698-alpha" + ] } \ No newline at end of file From 36a3eb4d3df87f358c5e0e282c6ab2dea0e06884 Mon Sep 17 00:00:00 2001 From: Bettina Heim Date: Thu, 15 Jul 2021 00:06:19 -0700 Subject: [PATCH 02/51] ... and here is where I'll leave it --- src/AzureClient/AzureClient.cs | 2 +- src/AzureClient/EntryPoint/EntryPoint.cs | 5 ++++- src/AzureClient/EntryPoint/EntryPointGenerator.cs | 5 ++++- src/AzureClient/EntryPoint/IEntryPoint.cs | 3 +++ src/Core/AssemblyInfo.cs | 8 ++++++-- src/Core/Compiler/CompilerService.cs | 14 ++++++++++++-- src/Core/Workspace/Workspace.cs | 6 +++--- 7 files changed, 33 insertions(+), 10 deletions(-) diff --git a/src/AzureClient/AzureClient.cs b/src/AzureClient/AzureClient.cs index 3ee34bf6c6..ff57f484a9 100644 --- a/src/AzureClient/AzureClient.cs +++ b/src/AzureClient/AzureClient.cs @@ -332,7 +332,7 @@ private async Task SubmitOrExecuteJobAsync( return AzureClientError.InvalidTarget.ToExecutionResult(); } - //submitter.SubmitAsync(qirStream, submissionContext.OperationName, new List(), Runtime.Submitters.SubmissionOptions.Default); + var job = await submitter.SubmitAsync(entryPoint.QirStream, submissionContext.OperationName, new List(), Runtime.Submitters.SubmissionOptions.Default); } else { diff --git a/src/AzureClient/EntryPoint/EntryPoint.cs b/src/AzureClient/EntryPoint/EntryPoint.cs index b445d155d6..fd15151c42 100644 --- a/src/AzureClient/EntryPoint/EntryPoint.cs +++ b/src/AzureClient/EntryPoint/EntryPoint.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Threading.Tasks; using Microsoft.Quantum.IQSharp.Jupyter; @@ -20,6 +21,7 @@ internal class EntryPoint : IEntryPoint private Type InputType { get; } private Type OutputType { get; } private OperationInfo OperationInfo { get; } + public Stream? QirStream { get; } /// /// Creates an object used to submit jobs to Azure Quantum. @@ -31,12 +33,13 @@ internal class EntryPoint : IEntryPoint /// Specifies the output parameter type for the /// object provided as the entryPointInfo argument. /// Information about the Q# operation to be used as the entry point. - public EntryPoint(object entryPointInfo, Type inputType, Type outputType, OperationInfo operationInfo) + public EntryPoint(object entryPointInfo, Type inputType, Type outputType, OperationInfo operationInfo, Stream qirStream) { EntryPointInfo = entryPointInfo; InputType = inputType; OutputType = outputType; OperationInfo = operationInfo; + QirStream = qirStream; } /// diff --git a/src/AzureClient/EntryPoint/EntryPointGenerator.cs b/src/AzureClient/EntryPoint/EntryPointGenerator.cs index a7b7bd419c..467e19908f 100644 --- a/src/AzureClient/EntryPoint/EntryPointGenerator.cs +++ b/src/AzureClient/EntryPoint/EntryPointGenerator.cs @@ -25,6 +25,7 @@ internal class EntryPointGenerator : IEntryPointGenerator private IWorkspace Workspace { get; } private ISnippets Snippets { get; } public IReferences References { get; } + public Stream QirStream { get; } public AssemblyInfo[] WorkspaceAssemblies { get; set; } = Array.Empty(); public AssemblyInfo? SnippetsAssemblyInfo { get; set; } public AssemblyInfo? EntryPointAssemblyInfo { get; set; } @@ -34,6 +35,7 @@ public EntryPointGenerator( IWorkspace workspace, ISnippets snippets, IReferences references, + Stream qirStream, ILogger logger, IEventService eventService) { @@ -41,6 +43,7 @@ public EntryPointGenerator( Workspace = workspace; Snippets = snippets; References = references; + QirStream = qirStream; Logger = logger; AssemblyLoadContext.Default.Resolving += Resolve; @@ -174,7 +177,7 @@ public IEntryPoint Generate(string operationName, string? executionTarget, var entryPointInfo = entryPointInfoType.GetConstructor(new Type[] { typeof(Type) }) .Invoke(new object[] { entryPointOperationInfo.RoslynType }); - return new EntryPoint(entryPointInfo, entryPointInputType, entryPointOutputType, entryPointOperationInfo); + return new EntryPoint(entryPointInfo, entryPointInputType, entryPointOutputType, entryPointOperationInfo, EntryPointAssemblyInfo.QirBitcode); } } } diff --git a/src/AzureClient/EntryPoint/IEntryPoint.cs b/src/AzureClient/EntryPoint/IEntryPoint.cs index aa3f78caa5..a9f32b109b 100644 --- a/src/AzureClient/EntryPoint/IEntryPoint.cs +++ b/src/AzureClient/EntryPoint/IEntryPoint.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; +using System.IO; using System.Text; using System.Threading.Tasks; using Microsoft.Quantum.Runtime; @@ -24,5 +25,7 @@ public interface IEntryPoint /// The object representing the submission context for the job. /// The details of the submitted job. public Task SubmitAsync(IQuantumMachine machine, AzureSubmissionContext submissionContext); + + public Stream QirStream { get; } } } diff --git a/src/Core/AssemblyInfo.cs b/src/Core/AssemblyInfo.cs index 6cc188343b..810a6f751b 100644 --- a/src/Core/AssemblyInfo.cs +++ b/src/Core/AssemblyInfo.cs @@ -9,6 +9,7 @@ using Microsoft.Quantum.IQSharp.Common; using Microsoft.Quantum.QsCompiler.SyntaxTree; using Microsoft.Quantum.QsCompiler; +using System.IO; namespace Microsoft.Quantum.IQSharp { @@ -25,18 +26,19 @@ public class AssemblyInfo : IEquatable /// /// Constructor for non Q# compiled assemblies. /// - public AssemblyInfo(Assembly assembly) : this(assembly, location: null, syntaxTree: null) + public AssemblyInfo(Assembly assembly) : this(assembly, location: null, syntaxTree: null, qirBitcode: null) { } /// /// Constructor for Q# compiled assemblies. /// - public AssemblyInfo(Assembly assembly, string location, QsNamespace[] syntaxTree) + public AssemblyInfo(Assembly assembly, string location, QsNamespace[] syntaxTree, Stream qirBitcode) { Assembly = assembly; Location = location ?? assembly?.Location; SyntaxTree = syntaxTree; + QirBitcode = qirBitcode; _operations = new Lazy(InitOperations); } @@ -55,6 +57,8 @@ public AssemblyInfo(Assembly assembly, string location, QsNamespace[] syntaxTree /// public QsNamespace[] SyntaxTree { get; } + public Stream QirBitcode { get; } + /// /// For Q#-based assemblies, the corresponding operations found in the SyntaxTree. /// diff --git a/src/Core/Compiler/CompilerService.cs b/src/Core/Compiler/CompilerService.cs index 2313b80a69..d4ff5583e4 100644 --- a/src/Core/Compiler/CompilerService.cs +++ b/src/Core/Compiler/CompilerService.cs @@ -249,6 +249,7 @@ string WrapInNamespace(Snippet s) => // Only create the serialization if we are compiling for an execution target: List? manifestResources = null; + Stream? qirStream = null; if (!string.IsNullOrEmpty(executionTarget)) { // Generate the assembly from the C# compilation: @@ -261,10 +262,18 @@ string WrapInNamespace(Snippet s) => return null; } + qirStream = new MemoryStream(); + // FIXME: get the qir stream ... -> the problem is: where do we get the llvm runtime libs from?? + manifestResources = new List() { new ResourceDescription( resourceName: DotnetCoreDll.ResourceNameQsDataBondV1, - dataProvider: () => new MemoryStream(serializedCompilation.ToArray()), + dataProvider: () => serializedCompilation, + isPublic: true + ), + new ResourceDescription( + resourceName: DotnetCoreDll.ResourceNameQsDataQirV1, + dataProvider: () => qirStream, isPublic: true ) }; @@ -302,7 +311,8 @@ string WrapInNamespace(Snippet s) => logger.LogError("IQS001", $"Unable to save assembly cache: {e.Message}."); } - return new AssemblyInfo(Assembly.Load(data), dllName, fromSources.ToArray()); + qirStream?.Seek(0, SeekOrigin.Begin); + return new AssemblyInfo(Assembly.Load(data), dllName, fromSources.ToArray(), qirStream); } } catch (Exception e) diff --git a/src/Core/Workspace/Workspace.cs b/src/Core/Workspace/Workspace.cs index a06b5e77dc..4d2a41699c 100644 --- a/src/Core/Workspace/Workspace.cs +++ b/src/Core/Workspace/Workspace.cs @@ -331,7 +331,7 @@ private bool LoadFromCache() Logger?.LogDebug($"Loading cache assembly: {project.CacheDllPath}."); var data = File.ReadAllBytes(project.CacheDllPath); var assm = System.Reflection.Assembly.Load(data); - project.AssemblyInfo = new AssemblyInfo(assm, project.CacheDllPath, null); + project.AssemblyInfo = new AssemblyInfo(assm, project.CacheDllPath, null, null); } ErrorMessages = new string[0]; @@ -499,7 +499,7 @@ private void DoReload(Action statusCallback = null) logger.LogError( "IQS003", $"Error compiling project {project.ProjectFile}: {e.Message}"); - project.AssemblyInfo = new AssemblyInfo(null, null, null); + project.AssemblyInfo = new AssemblyInfo(null); } ErrorMessages = ErrorMessages.Concat(logger.Errors.ToArray()); @@ -509,7 +509,7 @@ private void DoReload(Action statusCallback = null) else { Logger?.LogDebug($"No files found in project {project.ProjectFile}. Using empty workspace."); - project.AssemblyInfo = new AssemblyInfo(null, null, null); + project.AssemblyInfo = new AssemblyInfo(null); } if (!string.IsNullOrWhiteSpace(project.ProjectFile)) From 74b30c602a9ec4cafafab15c1fc6781fde73c94e Mon Sep 17 00:00:00 2001 From: Bettina Heim Date: Thu, 15 Jul 2021 18:40:24 -0700 Subject: [PATCH 03/51] more wip --- src/AzureClient/AzureClient.cs | 1 + src/AzureClient/AzureClient.csproj | 2 +- src/Core/Compiler/CompilerService.cs | 31 ++++++++++++++----- src/Core/Core.csproj | 9 +++--- .../ExecutionPathTracer.csproj | 2 +- .../Mock.Chemistry/Mock.Chemistry.csproj | 4 +-- .../Mock.Standard/Mock.Standard.csproj | 4 +-- .../ProjectA.csproj | 2 +- .../ProjectB.csproj | 2 +- .../Workspace.ProjectReferences.csproj | 4 +-- src/Tool/appsettings.json | 29 ++++++++--------- 11 files changed, 54 insertions(+), 36 deletions(-) diff --git a/src/AzureClient/AzureClient.cs b/src/AzureClient/AzureClient.cs index ff57f484a9..f5a8bfac72 100644 --- a/src/AzureClient/AzureClient.cs +++ b/src/AzureClient/AzureClient.cs @@ -332,6 +332,7 @@ private async Task SubmitOrExecuteJobAsync( return AzureClientError.InvalidTarget.ToExecutionResult(); } + channel?.Stdout(entryPoint.QirStream.ToString()); var job = await submitter.SubmitAsync(entryPoint.QirStream, submissionContext.OperationName, new List(), Runtime.Submitters.SubmissionOptions.Default); } else diff --git a/src/AzureClient/AzureClient.csproj b/src/AzureClient/AzureClient.csproj index 5b68fa8d7b..bc4973a567 100644 --- a/src/AzureClient/AzureClient.csproj +++ b/src/AzureClient/AzureClient.csproj @@ -13,7 +13,7 @@ - + diff --git a/src/Core/Compiler/CompilerService.cs b/src/Core/Compiler/CompilerService.cs index d4ff5583e4..add5b92e8c 100644 --- a/src/Core/Compiler/CompilerService.cs +++ b/src/Core/Compiler/CompilerService.cs @@ -19,6 +19,7 @@ using Microsoft.Quantum.QsCompiler; using Microsoft.Quantum.QsCompiler.CompilationBuilder; using Microsoft.Quantum.QsCompiler.CsharpGeneration; +using Microsoft.Quantum.QsCompiler.QIR; using Microsoft.Quantum.QsCompiler.ReservedKeywords; using Microsoft.Quantum.QsCompiler.SyntaxProcessing; using Microsoft.Quantum.QsCompiler.SyntaxTokens; @@ -262,21 +263,35 @@ string WrapInNamespace(Snippet s) => return null; } - qirStream = new MemoryStream(); - // FIXME: get the qir stream ... -> the problem is: where do we get the llvm runtime libs from?? - manifestResources = new List() { new ResourceDescription( resourceName: DotnetCoreDll.ResourceNameQsDataBondV1, dataProvider: () => serializedCompilation, isPublic: true - ), - new ResourceDescription( - resourceName: DotnetCoreDll.ResourceNameQsDataQirV1, - dataProvider: () => qirStream, - isPublic: true ) }; + + if (qsCompilation.EntryPoints.Any()) + { + using var generationContext = new GenerationContext(qsCompilation.Namespaces, isLibrary: false); + var generator = new Generator(qsCompilation, generationContext); + generator.Apply(); + + // write generated QIR to disk + var tempFileName = Path.GetTempFileName(); + var bcFile = CompilationLoader.GeneratedFile(tempFileName, Path.GetFullPath(tempFileName), ".bc", ""); + generator.Emit(bcFile, emitBitcode: false); + qirStream = File.OpenRead(bcFile); + + //manifestResources.Add( + // new ResourceDescription( + // resourceName: DotnetCoreDll.ResourceNameQsDataQirV1, + // dataProvider: () => qirStream, + // isPublic: true + // ) + //); + } + } using var ms = new MemoryStream(); diff --git a/src/Core/Core.csproj b/src/Core/Core.csproj index 182ff7dc5d..5d9a5b8637 100644 --- a/src/Core/Core.csproj +++ b/src/Core/Core.csproj @@ -38,10 +38,11 @@ - - - - + + + + + diff --git a/src/ExecutionPathTracer/ExecutionPathTracer.csproj b/src/ExecutionPathTracer/ExecutionPathTracer.csproj index 1b67ed7df1..9e2a1bd070 100644 --- a/src/ExecutionPathTracer/ExecutionPathTracer.csproj +++ b/src/ExecutionPathTracer/ExecutionPathTracer.csproj @@ -32,7 +32,7 @@ - + diff --git a/src/MockLibraries/Mock.Chemistry/Mock.Chemistry.csproj b/src/MockLibraries/Mock.Chemistry/Mock.Chemistry.csproj index 4be18ee4f5..8358bb9f26 100644 --- a/src/MockLibraries/Mock.Chemistry/Mock.Chemistry.csproj +++ b/src/MockLibraries/Mock.Chemistry/Mock.Chemistry.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 @@ -6,6 +6,6 @@ - + diff --git a/src/MockLibraries/Mock.Standard/Mock.Standard.csproj b/src/MockLibraries/Mock.Standard/Mock.Standard.csproj index 4be18ee4f5..8358bb9f26 100644 --- a/src/MockLibraries/Mock.Standard/Mock.Standard.csproj +++ b/src/MockLibraries/Mock.Standard/Mock.Standard.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 @@ -6,6 +6,6 @@ - + diff --git a/src/Tests/Workspace.ProjectReferences.ProjectA/ProjectA.csproj b/src/Tests/Workspace.ProjectReferences.ProjectA/ProjectA.csproj index 7e5facf9f5..4da77ed345 100644 --- a/src/Tests/Workspace.ProjectReferences.ProjectA/ProjectA.csproj +++ b/src/Tests/Workspace.ProjectReferences.ProjectA/ProjectA.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 diff --git a/src/Tests/Workspace.ProjectReferences.ProjectB/ProjectB.csproj b/src/Tests/Workspace.ProjectReferences.ProjectB/ProjectB.csproj index 78f8f21169..83c3dc70c8 100644 --- a/src/Tests/Workspace.ProjectReferences.ProjectB/ProjectB.csproj +++ b/src/Tests/Workspace.ProjectReferences.ProjectB/ProjectB.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 diff --git a/src/Tests/Workspace.ProjectReferences/Workspace.ProjectReferences.csproj b/src/Tests/Workspace.ProjectReferences/Workspace.ProjectReferences.csproj index 1d1b7db9ac..eb83eaac70 100644 --- a/src/Tests/Workspace.ProjectReferences/Workspace.ProjectReferences.csproj +++ b/src/Tests/Workspace.ProjectReferences/Workspace.ProjectReferences.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 @@ -7,7 +7,7 @@ - + diff --git a/src/Tool/appsettings.json b/src/Tool/appsettings.json index 4c8e4b4490..bb0e25d7d0 100644 --- a/src/Tool/appsettings.json +++ b/src/Tool/appsettings.json @@ -6,21 +6,22 @@ }, "AllowedHosts": "*", "DefaultPackageVersions": [ - "Microsoft.Quantum.Compiler::0.18.2107150698-alpha", - "Microsoft.Quantum.CSharpGeneration::0.18.2107150698-alpha", - "Microsoft.Quantum.Development.Kit::0.18.2107150698-alpha", - "Microsoft.Quantum.Simulators::0.18.2107150698-alpha", - "Microsoft.Quantum.Xunit::0.18.2107150698-alpha", - "Microsoft.Quantum.Standard::0.18.2107150698-alpha", - "Microsoft.Quantum.Standard.Visualization::0.18.2107150698-alpha", - "Microsoft.Quantum.Chemistry::0.18.2107150698-alpha", - "Microsoft.Quantum.Chemistry.Jupyter::0.18.2107150698-alpha", - "Microsoft.Quantum.MachineLearning::0.18.2107150698-alpha", - "Microsoft.Quantum.Numerics::0.18.2107150698-alpha", - "Microsoft.Quantum.Katas::0.18.2107150698-alpha", - "Microsoft.Quantum.Research::0.18.2107150698-alpha", + "Microsoft.Quantum.Compiler::0.18.210729343-alpha", + "Microsoft.Quantum.CSharpGeneration::0.18.210729343-alpha", + "Microsoft.Quantum.Development.Kit::0.18.210729343-alpha", + "Microsoft.Quantum.Simulators::0.18.210729343-alpha", + "Microsoft.Quantum.Xunit::0.18.210729343-alpha", + "Microsoft.Quantum.Standard::0.18.210729343-alpha", + "Microsoft.Quantum.Standard.Visualization::0.18.210729343-alpha", + "Microsoft.Quantum.Chemistry::0.18.210729343-alpha", + "Microsoft.Quantum.Chemistry.Jupyter::0.18.210729343-alpha", + "Microsoft.Quantum.MachineLearning::0.18.210729343-alpha", + "Microsoft.Quantum.Numerics::0.18.210729343-alpha", + "Microsoft.Quantum.Katas::0.18.210729343-alpha", + "Microsoft.Quantum.Research::0.18.210729343-alpha", "Microsoft.Quantum.Providers.IonQ::0.18.2107150698-alpha", "Microsoft.Quantum.Providers.Honeywell::0.18.2107150698-alpha", - "Microsoft.Quantum.Providers.QCI::0.18.2107150698-alpha" + "Microsoft.Quantum.Providers.QCI::0.18.2107150698-alpha", + "Microsoft.Quantum.Providers.Core::0.18.2107150698-alpha" ] } \ No newline at end of file From 51f3cd18f425594031e39323f56ea3a77b6e8d4b Mon Sep 17 00:00:00 2001 From: Bettina Heim Date: Thu, 15 Jul 2021 19:04:00 -0700 Subject: [PATCH 04/51] removing handle --- src/AzureClient/EntryPoint/EntryPointGenerator.cs | 3 --- src/Core/Compiler/ICompilerService.cs | 1 + 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/AzureClient/EntryPoint/EntryPointGenerator.cs b/src/AzureClient/EntryPoint/EntryPointGenerator.cs index 467e19908f..2989cda2ef 100644 --- a/src/AzureClient/EntryPoint/EntryPointGenerator.cs +++ b/src/AzureClient/EntryPoint/EntryPointGenerator.cs @@ -25,7 +25,6 @@ internal class EntryPointGenerator : IEntryPointGenerator private IWorkspace Workspace { get; } private ISnippets Snippets { get; } public IReferences References { get; } - public Stream QirStream { get; } public AssemblyInfo[] WorkspaceAssemblies { get; set; } = Array.Empty(); public AssemblyInfo? SnippetsAssemblyInfo { get; set; } public AssemblyInfo? EntryPointAssemblyInfo { get; set; } @@ -35,7 +34,6 @@ public EntryPointGenerator( IWorkspace workspace, ISnippets snippets, IReferences references, - Stream qirStream, ILogger logger, IEventService eventService) { @@ -43,7 +41,6 @@ public EntryPointGenerator( Workspace = workspace; Snippets = snippets; References = references; - QirStream = qirStream; Logger = logger; AssemblyLoadContext.Default.Resolving += Resolve; diff --git a/src/Core/Compiler/ICompilerService.cs b/src/Core/Compiler/ICompilerService.cs index dc3229c71f..aa280cc938 100644 --- a/src/Core/Compiler/ICompilerService.cs +++ b/src/Core/Compiler/ICompilerService.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.IO; using Microsoft.Quantum.IQSharp.Common; using Microsoft.Quantum.QsCompiler; using Microsoft.Quantum.QsCompiler.ReservedKeywords; From 9e26d74f305f51f1b6c6b7e332c724bf702ef12a Mon Sep 17 00:00:00 2001 From: Bettina Heim Date: Thu, 15 Jul 2021 19:13:39 -0700 Subject: [PATCH 05/51] could not find llvmlib --- src/Core/Compiler/CompilerService.cs | 2 +- src/Core/Compiler/ICompilerService.cs | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Core/Compiler/CompilerService.cs b/src/Core/Compiler/CompilerService.cs index add5b92e8c..5a785aa1ac 100644 --- a/src/Core/Compiler/CompilerService.cs +++ b/src/Core/Compiler/CompilerService.cs @@ -266,7 +266,7 @@ string WrapInNamespace(Snippet s) => manifestResources = new List() { new ResourceDescription( resourceName: DotnetCoreDll.ResourceNameQsDataBondV1, - dataProvider: () => serializedCompilation, + dataProvider: () => new MemoryStream(serializedCompilation.ToArray()), isPublic: true ) }; diff --git a/src/Core/Compiler/ICompilerService.cs b/src/Core/Compiler/ICompilerService.cs index aa280cc938..746e923f22 100644 --- a/src/Core/Compiler/ICompilerService.cs +++ b/src/Core/Compiler/ICompilerService.cs @@ -3,10 +3,8 @@ using System; using System.Collections.Generic; -using System.IO; using Microsoft.Quantum.IQSharp.Common; using Microsoft.Quantum.QsCompiler; -using Microsoft.Quantum.QsCompiler.ReservedKeywords; using Microsoft.Quantum.QsCompiler.SyntaxTree; namespace Microsoft.Quantum.IQSharp From 2e30505659b9a4a7a4f0fbe741fccbfd800a911d Mon Sep 17 00:00:00 2001 From: Bettina Heim Date: Thu, 15 Jul 2021 19:34:09 -0700 Subject: [PATCH 06/51] the basics work --- src/AzureClient/AzureClient.cs | 4 +++- src/Core/Compiler/CompilerService.cs | 4 ++-- src/Tests/Tests.IQsharp.csproj | 15 +++++++++++++++ src/Tool/Tool.csproj | 17 ++++++++++++++++- src/Web/Web.csproj | 15 +++++++++++++++ 5 files changed, 51 insertions(+), 4 deletions(-) diff --git a/src/AzureClient/AzureClient.cs b/src/AzureClient/AzureClient.cs index f5a8bfac72..7ca60a5fea 100644 --- a/src/AzureClient/AzureClient.cs +++ b/src/AzureClient/AzureClient.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.IO; using System.Linq; using System.Net; using System.Threading; @@ -332,7 +333,8 @@ private async Task SubmitOrExecuteJobAsync( return AzureClientError.InvalidTarget.ToExecutionResult(); } - channel?.Stdout(entryPoint.QirStream.ToString()); + var reader = new StreamReader(entryPoint.QirStream); + channel?.Stdout(reader.ReadToEnd()); var job = await submitter.SubmitAsync(entryPoint.QirStream, submissionContext.OperationName, new List(), Runtime.Submitters.SubmissionOptions.Default); } else diff --git a/src/Core/Compiler/CompilerService.cs b/src/Core/Compiler/CompilerService.cs index 5a785aa1ac..dfdeb5ca1d 100644 --- a/src/Core/Compiler/CompilerService.cs +++ b/src/Core/Compiler/CompilerService.cs @@ -278,8 +278,8 @@ string WrapInNamespace(Snippet s) => generator.Apply(); // write generated QIR to disk - var tempFileName = Path.GetTempFileName(); - var bcFile = CompilationLoader.GeneratedFile(tempFileName, Path.GetFullPath(tempFileName), ".bc", ""); + var tempPath = Path.GetTempPath(); + var bcFile = CompilationLoader.GeneratedFile(Path.Combine(tempPath, Path.GetRandomFileName()), tempPath, ".ll", ""); generator.Emit(bcFile, emitBitcode: false); qirStream = File.OpenRead(bcFile); diff --git a/src/Tests/Tests.IQsharp.csproj b/src/Tests/Tests.IQsharp.csproj index 507ec365cd..2dd7a79dfe 100644 --- a/src/Tests/Tests.IQsharp.csproj +++ b/src/Tests/Tests.IQsharp.csproj @@ -42,6 +42,21 @@ + + + + + + + PreserveNewest diff --git a/src/Tool/Tool.csproj b/src/Tool/Tool.csproj index 5872a1cf2e..d045248ea0 100644 --- a/src/Tool/Tool.csproj +++ b/src/Tool/Tool.csproj @@ -24,7 +24,22 @@ \ - + + + + + + + + diff --git a/src/Web/Web.csproj b/src/Web/Web.csproj index 913d5d6017..21ca74be50 100644 --- a/src/Web/Web.csproj +++ b/src/Web/Web.csproj @@ -7,6 +7,21 @@ Microsoft.Quantum.IQSharp.Web + + + + + + + From 947a4cadb8221ce6f29197bb5d1f676e46c7b0c4 Mon Sep 17 00:00:00 2001 From: Bettina Heim Date: Fri, 16 Jul 2021 11:59:35 -0700 Subject: [PATCH 07/51] updating compiler package to prepare QIR generation --- src/AzureClient/AzureClient.cs | 11 +++++++- src/AzureClient/AzureClient.csproj | 2 +- src/Core/Compiler/CompilerService.cs | 15 ++++++++--- src/Core/Core.csproj | 10 +++---- .../ExecutionPathTracer.csproj | 2 +- .../Mock.Chemistry/Mock.Chemistry.csproj | 4 +-- .../Mock.Standard/Mock.Standard.csproj | 4 +-- .../ProjectA.csproj | 2 +- .../ProjectB.csproj | 2 +- .../Workspace.ProjectReferences.csproj | 4 +-- src/Tool/appsettings.json | 26 +++++++++---------- 11 files changed, 49 insertions(+), 33 deletions(-) diff --git a/src/AzureClient/AzureClient.cs b/src/AzureClient/AzureClient.cs index 7ca60a5fea..ed4e2968b7 100644 --- a/src/AzureClient/AzureClient.cs +++ b/src/AzureClient/AzureClient.cs @@ -335,7 +335,16 @@ private async Task SubmitOrExecuteJobAsync( var reader = new StreamReader(entryPoint.QirStream); channel?.Stdout(reader.ReadToEnd()); - var job = await submitter.SubmitAsync(entryPoint.QirStream, submissionContext.OperationName, new List(), Runtime.Submitters.SubmissionOptions.Default); + + //var job = await submitter.SubmitAsync( + // entryPoint.QirStream, + // submissionContext.OperationName, + // new List(), + // Runtime.Submitters.SubmissionOptions.Default.With(friendlyName: submissionContext.OperationName, shots: 1)); + //channel?.Stdout($"Job successfully submitted for {submissionContext.Shots} shots."); + //channel?.Stdout($" Job name: {submissionContext.FriendlyName}"); + //channel?.Stdout($" Job ID: {job.Id}"); + //MostRecentJobId = job.Id; } else { diff --git a/src/AzureClient/AzureClient.csproj b/src/AzureClient/AzureClient.csproj index bc4973a567..85ad53c15f 100644 --- a/src/AzureClient/AzureClient.csproj +++ b/src/AzureClient/AzureClient.csproj @@ -13,7 +13,7 @@ - + diff --git a/src/Core/Compiler/CompilerService.cs b/src/Core/Compiler/CompilerService.cs index dfdeb5ca1d..dd8996d15d 100644 --- a/src/Core/Compiler/CompilerService.cs +++ b/src/Core/Compiler/CompilerService.cs @@ -26,6 +26,8 @@ using Microsoft.Quantum.QsCompiler.SyntaxTree; using Microsoft.Quantum.QsCompiler.Transformations.BasicTransformations; using Microsoft.Quantum.QsCompiler.Transformations.QsCodeOutput; +using Microsoft.Quantum.QsCompiler.Transformations.SyntaxTreeTrimming; +using Microsoft.Quantum.QsCompiler.Transformations.Targeting; using QsReferences = Microsoft.Quantum.QsCompiler.CompilationBuilder.References; @@ -136,7 +138,8 @@ public IEnumerable IdentifyElements(string source) LoadReferencesBasedOnGeneratedCsharp = string.IsNullOrEmpty(executionTarget), // deserialization of resources in references is only needed if there is an execution target IsExecutable = compileAsExecutable, AssemblyConstants = new Dictionary { [AssemblyConstants.ProcessorArchitecture] = executionTarget ?? string.Empty }, - RuntimeCapability = runtimeCapability ?? RuntimeCapability.FullComputation + RuntimeCapability = runtimeCapability ?? RuntimeCapability.FullComputation, + PrepareQirGeneration = executionTarget?.StartsWith("microsoft.simulator") ?? false }; var loaded = new CompilationLoader(_ => sources, _ => references, loadOptions, logger); return loaded.CompilationOutput; @@ -273,13 +276,17 @@ string WrapInNamespace(Snippet s) => if (qsCompilation.EntryPoints.Any()) { - using var generationContext = new GenerationContext(qsCompilation.Namespaces, isLibrary: false); - var generator = new Generator(qsCompilation, generationContext); + var transformed = TrimSyntaxTree.Apply(qsCompilation, keepAllIntrinsics: false); + transformed = InferTargetInstructions.ReplaceSelfAdjointSpecializations(transformed); + transformed = InferTargetInstructions.LiftIntrinsicSpecializations(transformed); + var allAttributesAdded = InferTargetInstructions.TryAddMissingTargetInstructionAttributes(transformed, out transformed); + + using var generator = new Generator(transformed); generator.Apply(); // write generated QIR to disk var tempPath = Path.GetTempPath(); - var bcFile = CompilationLoader.GeneratedFile(Path.Combine(tempPath, Path.GetRandomFileName()), tempPath, ".ll", ""); + var bcFile = CompilationLoader.GeneratedFile(Path.Combine(tempPath, Path.GetRandomFileName()), tempPath, ".bc", ""); generator.Emit(bcFile, emitBitcode: false); qirStream = File.OpenRead(bcFile); diff --git a/src/Core/Core.csproj b/src/Core/Core.csproj index 5d9a5b8637..d88b30420c 100644 --- a/src/Core/Core.csproj +++ b/src/Core/Core.csproj @@ -38,11 +38,11 @@ - - - - - + + + + + diff --git a/src/ExecutionPathTracer/ExecutionPathTracer.csproj b/src/ExecutionPathTracer/ExecutionPathTracer.csproj index 9e2a1bd070..fc5be105fb 100644 --- a/src/ExecutionPathTracer/ExecutionPathTracer.csproj +++ b/src/ExecutionPathTracer/ExecutionPathTracer.csproj @@ -32,7 +32,7 @@ - + diff --git a/src/MockLibraries/Mock.Chemistry/Mock.Chemistry.csproj b/src/MockLibraries/Mock.Chemistry/Mock.Chemistry.csproj index 8358bb9f26..25f285cd24 100644 --- a/src/MockLibraries/Mock.Chemistry/Mock.Chemistry.csproj +++ b/src/MockLibraries/Mock.Chemistry/Mock.Chemistry.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 @@ -6,6 +6,6 @@ - + diff --git a/src/MockLibraries/Mock.Standard/Mock.Standard.csproj b/src/MockLibraries/Mock.Standard/Mock.Standard.csproj index 8358bb9f26..25f285cd24 100644 --- a/src/MockLibraries/Mock.Standard/Mock.Standard.csproj +++ b/src/MockLibraries/Mock.Standard/Mock.Standard.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 @@ -6,6 +6,6 @@ - + diff --git a/src/Tests/Workspace.ProjectReferences.ProjectA/ProjectA.csproj b/src/Tests/Workspace.ProjectReferences.ProjectA/ProjectA.csproj index 4da77ed345..4ad401a891 100644 --- a/src/Tests/Workspace.ProjectReferences.ProjectA/ProjectA.csproj +++ b/src/Tests/Workspace.ProjectReferences.ProjectA/ProjectA.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 diff --git a/src/Tests/Workspace.ProjectReferences.ProjectB/ProjectB.csproj b/src/Tests/Workspace.ProjectReferences.ProjectB/ProjectB.csproj index 83c3dc70c8..de2f56a308 100644 --- a/src/Tests/Workspace.ProjectReferences.ProjectB/ProjectB.csproj +++ b/src/Tests/Workspace.ProjectReferences.ProjectB/ProjectB.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 diff --git a/src/Tests/Workspace.ProjectReferences/Workspace.ProjectReferences.csproj b/src/Tests/Workspace.ProjectReferences/Workspace.ProjectReferences.csproj index eb83eaac70..f3bff46da9 100644 --- a/src/Tests/Workspace.ProjectReferences/Workspace.ProjectReferences.csproj +++ b/src/Tests/Workspace.ProjectReferences/Workspace.ProjectReferences.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 @@ -7,7 +7,7 @@ - + diff --git a/src/Tool/appsettings.json b/src/Tool/appsettings.json index bb0e25d7d0..62bb2c976b 100644 --- a/src/Tool/appsettings.json +++ b/src/Tool/appsettings.json @@ -6,19 +6,19 @@ }, "AllowedHosts": "*", "DefaultPackageVersions": [ - "Microsoft.Quantum.Compiler::0.18.210729343-alpha", - "Microsoft.Quantum.CSharpGeneration::0.18.210729343-alpha", - "Microsoft.Quantum.Development.Kit::0.18.210729343-alpha", - "Microsoft.Quantum.Simulators::0.18.210729343-alpha", - "Microsoft.Quantum.Xunit::0.18.210729343-alpha", - "Microsoft.Quantum.Standard::0.18.210729343-alpha", - "Microsoft.Quantum.Standard.Visualization::0.18.210729343-alpha", - "Microsoft.Quantum.Chemistry::0.18.210729343-alpha", - "Microsoft.Quantum.Chemistry.Jupyter::0.18.210729343-alpha", - "Microsoft.Quantum.MachineLearning::0.18.210729343-alpha", - "Microsoft.Quantum.Numerics::0.18.210729343-alpha", - "Microsoft.Quantum.Katas::0.18.210729343-alpha", - "Microsoft.Quantum.Research::0.18.210729343-alpha", + "Microsoft.Quantum.Compiler::0.18.210729377-pull", + "Microsoft.Quantum.CSharpGeneration::0.18.210729377-pull", + "Microsoft.Quantum.Development.Kit::0.18.210729377-pull", + "Microsoft.Quantum.Simulators::0.18.210729377-pull", + "Microsoft.Quantum.Xunit::0.18.210729377-pull", + "Microsoft.Quantum.Standard::0.18.210729377-pull", + "Microsoft.Quantum.Standard.Visualization::0.18.210729377-pull", + "Microsoft.Quantum.Chemistry::0.18.210729377-pull", + "Microsoft.Quantum.Chemistry.Jupyter::0.18.210729377-pull", + "Microsoft.Quantum.MachineLearning::0.18.210729377-pull", + "Microsoft.Quantum.Numerics::0.18.210729377-pull", + "Microsoft.Quantum.Katas::0.18.210729377-pull", + "Microsoft.Quantum.Research::0.18.210729377-pull", "Microsoft.Quantum.Providers.IonQ::0.18.2107150698-alpha", "Microsoft.Quantum.Providers.Honeywell::0.18.2107150698-alpha", "Microsoft.Quantum.Providers.QCI::0.18.2107150698-alpha", From 47f183d948bfde2be7729b3c7e1a863be58d715b Mon Sep 17 00:00:00 2001 From: Bettina Heim Date: Fri, 16 Jul 2021 17:24:29 -0700 Subject: [PATCH 08/51] some minor things during debugging --- src/Core/AssemblyInfo.cs | 2 +- src/Core/Compiler/CompilerMetadata.cs | 7 +++++-- src/Core/Compiler/CompilerService.cs | 4 ++-- src/Core/References/References.cs | 17 +++++++++++++++-- 4 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/Core/AssemblyInfo.cs b/src/Core/AssemblyInfo.cs index 810a6f751b..8551a39a3f 100644 --- a/src/Core/AssemblyInfo.cs +++ b/src/Core/AssemblyInfo.cs @@ -74,7 +74,7 @@ private OperationInfo[] InitOperations() // Parse the assembly headers to find which types are operation or function types. var logger = new QSharpLogger(null); - var refs = ProjectManager.LoadReferencedAssemblies(new[] { Location }, d => logger.Log(d), ex => logger.Log(ex), ignoreDllResources:CompilerMetadata.LoadFromCsharp); + var refs = ProjectManager.LoadReferencedAssemblies(new[] { Location }, d => logger.Log(d), ex => logger.Log(ex), ignoreDllResources: false); var callables = refs.SelectMany(pair => pair.Value.Callables); diff --git a/src/Core/Compiler/CompilerMetadata.cs b/src/Core/Compiler/CompilerMetadata.cs index c41140fedf..2d2b7c2829 100644 --- a/src/Core/Compiler/CompilerMetadata.cs +++ b/src/Core/Compiler/CompilerMetadata.cs @@ -95,8 +95,11 @@ private static ImmutableArray RoslynInit(IEnumerable /// /// Calculates Q# metadata needed for all the Assemblies and their dependencies. /// - private static QsReferences QsInit(IEnumerable paths) => - new QsReferences(ProjectManager.LoadReferencedAssemblies(paths, ignoreDllResources:CompilerMetadata.LoadFromCsharp)); + private static QsReferences QsInit(IEnumerable paths) + { + var loaded = new QsReferences(ProjectManager.LoadReferencedAssemblies(paths, ignoreDllResources: false)); + return loaded; + } public CompilerMetadata WithAssemblies(params AssemblyInfo[] assemblies) { diff --git a/src/Core/Compiler/CompilerService.cs b/src/Core/Compiler/CompilerService.cs index dd8996d15d..ca48f601bf 100644 --- a/src/Core/Compiler/CompilerService.cs +++ b/src/Core/Compiler/CompilerService.cs @@ -268,7 +268,7 @@ string WrapInNamespace(Snippet s) => manifestResources = new List() { new ResourceDescription( - resourceName: DotnetCoreDll.ResourceNameQsDataBondV1, + resourceName: DotnetCoreDll.SyntaxTreeResourceName, dataProvider: () => new MemoryStream(serializedCompilation.ToArray()), isPublic: true ) @@ -292,7 +292,7 @@ string WrapInNamespace(Snippet s) => //manifestResources.Add( // new ResourceDescription( - // resourceName: DotnetCoreDll.ResourceNameQsDataQirV1, + // resourceName: DotnetCoreDll.QirResource, // dataProvider: () => qirStream, // isPublic: true // ) diff --git a/src/Core/References/References.cs b/src/Core/References/References.cs index 0c64836e84..11e117fd71 100644 --- a/src/Core/References/References.cs +++ b/src/Core/References/References.cs @@ -10,6 +10,7 @@ using System.Linq.Expressions; using System.Reflection; using System.Runtime.Loader; +using System.Text.RegularExpressions; using System.Threading.Tasks; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; @@ -100,7 +101,9 @@ IOptions options AutoLoadPackages = ParsePackages(autoLoadPkgs); } - _metadata = new Lazy(() => new CompilerMetadata(this.Assemblies)); + // The call to Reset below ensures that _metadata is not null. + Reset(); + Debug.Assert(_metadata != null); AssemblyLoadContext.Default.Resolving += Resolve; } @@ -178,9 +181,19 @@ public async Task AddPackage(string name, Action? statusCallback = null) private void Reset() { - _metadata = new Lazy(() => new CompilerMetadata(this.Assemblies)); + _metadata = new Lazy(() => new CompilerMetadata( + this.Assemblies.Where(IsAssemblyPossiblyQSharpReference) + )); } + private static bool IsAssemblyPossiblyQSharpReference(AssemblyInfo arg) => + !Regex.Match( + arg.Assembly.GetName().Name, + // Reference filtering should match the filtering at + // https://github.com/microsoft/qsharp-compiler/blob/c3d1a09f70960d09af68e805294962e7e6c690d8/src/QuantumSdk/Sdk/Sdk.targets#L70. + "(?i)system.|mscorlib|netstandard.library|microsoft.netcore.app|csharp|fsharp|microsoft.visualstudio|microsoft.testplatform|microsoft.codeanalysis|fparsec|newtonsoft|roslynwrapper|yamldotnet|markdig|serilog" + ).Success; + /// /// Because the assemblies are loaded into memory, we need to provide this method to the AssemblyLoadContext /// such that the Workspace assembly or this assembly is correctly resolved when it is executed for simulation. From de9a651574b939473d7acfc2bfb12330ea34aae9 Mon Sep 17 00:00:00 2001 From: Bettina Heim Date: Fri, 16 Jul 2021 20:13:54 -0700 Subject: [PATCH 09/51] fixing the missing reference implementations --- src/AzureClient/AzureClient.cs | 24 ++++++------ src/Core/Compiler/CompilerMetadata.cs | 10 +++-- src/Core/Compiler/CompilerService.cs | 53 ++++++++++++++------------- 3 files changed, 46 insertions(+), 41 deletions(-) diff --git a/src/AzureClient/AzureClient.cs b/src/AzureClient/AzureClient.cs index ed4e2968b7..6dc51c5e79 100644 --- a/src/AzureClient/AzureClient.cs +++ b/src/AzureClient/AzureClient.cs @@ -333,18 +333,18 @@ private async Task SubmitOrExecuteJobAsync( return AzureClientError.InvalidTarget.ToExecutionResult(); } - var reader = new StreamReader(entryPoint.QirStream); - channel?.Stdout(reader.ReadToEnd()); - - //var job = await submitter.SubmitAsync( - // entryPoint.QirStream, - // submissionContext.OperationName, - // new List(), - // Runtime.Submitters.SubmissionOptions.Default.With(friendlyName: submissionContext.OperationName, shots: 1)); - //channel?.Stdout($"Job successfully submitted for {submissionContext.Shots} shots."); - //channel?.Stdout($" Job name: {submissionContext.FriendlyName}"); - //channel?.Stdout($" Job ID: {job.Id}"); - //MostRecentJobId = job.Id; + //var reader = new StreamReader(entryPoint.QirStream); + //channel?.Stdout(reader.ReadToEnd()); + + var job = await submitter.SubmitAsync( + entryPoint.QirStream, + submissionContext.OperationName, + new List(), + Runtime.Submitters.SubmissionOptions.Default.With(friendlyName: submissionContext.OperationName, shots: 1)); + channel?.Stdout($"Job successfully submitted for {submissionContext.Shots} shots."); + channel?.Stdout($" Job name: {submissionContext.FriendlyName}"); + channel?.Stdout($" Job ID: {job.Id}"); + MostRecentJobId = job.Id; } else { diff --git a/src/Core/Compiler/CompilerMetadata.cs b/src/Core/Compiler/CompilerMetadata.cs index 2d2b7c2829..a179dfac51 100644 --- a/src/Core/Compiler/CompilerMetadata.cs +++ b/src/Core/Compiler/CompilerMetadata.cs @@ -17,7 +17,7 @@ namespace Microsoft.Quantum.IQSharp { public class CompilerMetadata { - internal static readonly bool LoadFromCsharp = true; // todo: we should make this properly configurable + internal static readonly bool LoadFromCsharp = false; // todo: we should make this properly configurable private IEnumerable Paths { get; } @@ -97,8 +97,12 @@ private static ImmutableArray RoslynInit(IEnumerable /// private static QsReferences QsInit(IEnumerable paths) { - var loaded = new QsReferences(ProjectManager.LoadReferencedAssemblies(paths, ignoreDllResources: false)); - return loaded; + var headers = ProjectManager.LoadReferencedAssembliesInParallel( + paths, + ignoreDllResources: false); + + var references = new QsReferences(headers); + return references; } public CompilerMetadata WithAssemblies(params AssemblyInfo[] assemblies) diff --git a/src/Core/Compiler/CompilerService.cs b/src/Core/Compiler/CompilerService.cs index ca48f601bf..108903f30f 100644 --- a/src/Core/Compiler/CompilerService.cs +++ b/src/Core/Compiler/CompilerService.cs @@ -212,7 +212,8 @@ string WrapInNamespace(Snippet s) => /// /// Builds the corresponding .net core assembly from the Q# syntax tree. /// - private AssemblyInfo? BuildAssembly(ImmutableDictionary sources, CompilerMetadata metadata, QSharpLogger logger, string dllName, bool compileAsExecutable, string? executionTarget, + private AssemblyInfo? BuildAssembly(ImmutableDictionary sources, CompilerMetadata metadata, QSharpLogger logger, + string dllName, bool compileAsExecutable, string? executionTarget, RuntimeCapability? runtimeCapability = null) { logger.LogDebug($"Compiling the following Q# files: {string.Join(",", sources.Keys.Select(f => f.LocalPath))}"); @@ -254,7 +255,7 @@ string WrapInNamespace(Snippet s) => // Only create the serialization if we are compiling for an execution target: List? manifestResources = null; Stream? qirStream = null; - if (!string.IsNullOrEmpty(executionTarget)) + if (string.IsNullOrEmpty(executionTarget)) { // Generate the assembly from the C# compilation: var syntaxTree = new QsCompilation(fromSources.ToImmutableArray(), qsCompilation.EntryPoints); @@ -274,32 +275,32 @@ string WrapInNamespace(Snippet s) => ) }; - if (qsCompilation.EntryPoints.Any()) - { - var transformed = TrimSyntaxTree.Apply(qsCompilation, keepAllIntrinsics: false); - transformed = InferTargetInstructions.ReplaceSelfAdjointSpecializations(transformed); - transformed = InferTargetInstructions.LiftIntrinsicSpecializations(transformed); - var allAttributesAdded = InferTargetInstructions.TryAddMissingTargetInstructionAttributes(transformed, out transformed); - - using var generator = new Generator(transformed); - generator.Apply(); - - // write generated QIR to disk - var tempPath = Path.GetTempPath(); - var bcFile = CompilationLoader.GeneratedFile(Path.Combine(tempPath, Path.GetRandomFileName()), tempPath, ".bc", ""); - generator.Emit(bcFile, emitBitcode: false); - qirStream = File.OpenRead(bcFile); - - //manifestResources.Add( - // new ResourceDescription( - // resourceName: DotnetCoreDll.QirResource, - // dataProvider: () => qirStream, - // isPublic: true - // ) - //); - } } + else if (qsCompilation.EntryPoints.Any()) + { + var transformed = TrimSyntaxTree.Apply(qsCompilation, keepAllIntrinsics: false); + transformed = InferTargetInstructions.ReplaceSelfAdjointSpecializations(transformed); + transformed = InferTargetInstructions.LiftIntrinsicSpecializations(transformed); + var allAttributesAdded = InferTargetInstructions.TryAddMissingTargetInstructionAttributes(transformed, out transformed); + + using var generator = new Generator(transformed); + generator.Apply(); + + // write generated QIR to disk + var tempPath = Path.GetTempPath(); + var bcFile = CompilationLoader.GeneratedFile(Path.Combine(tempPath, Path.GetRandomFileName()), tempPath, ".bc", ""); + generator.Emit(bcFile, emitBitcode: true); + qirStream = File.OpenRead(bcFile); + + //manifestResources.Add( + // new ResourceDescription( + // resourceName: DotnetCoreDll.QirResource, + // dataProvider: () => qirStream, + // isPublic: true + // ) + //); + } using var ms = new MemoryStream(); var result = compilation.Emit(ms, manifestResources: manifestResources); From bfd3e9f114bd71732d2ee0ce01f3cf91d1dd7799 Mon Sep 17 00:00:00 2001 From: Bettina Heim Date: Fri, 16 Jul 2021 21:25:07 -0700 Subject: [PATCH 10/51] working proof of concept (could be done nicer) --- src/AzureClient/AzureClient.cs | 11 +++++--- .../Visualization/HistogramEncoders.cs | 28 ++++++++++++++++++- 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/src/AzureClient/AzureClient.cs b/src/AzureClient/AzureClient.cs index 6dc51c5e79..2e89552aaa 100644 --- a/src/AzureClient/AzureClient.cs +++ b/src/AzureClient/AzureClient.cs @@ -324,7 +324,6 @@ private async Task SubmitOrExecuteJobAsync( if (this.ActiveTarget.TargetId.StartsWith(MicrosoftSimulator)) { - channel?.Stdout("Preparing to submit to Microsoft simulator..."); var submitter = SubmitterFactory.QirSubmitter(this.ActiveTarget.TargetId, this.ActiveWorkspace, this.StorageConnectionString); if (submitter == null) { @@ -335,13 +334,14 @@ private async Task SubmitOrExecuteJobAsync( //var reader = new StreamReader(entryPoint.QirStream); //channel?.Stdout(reader.ReadToEnd()); + //entryPoint.QirStream.Seek(0, SeekOrigin.Begin); var job = await submitter.SubmitAsync( entryPoint.QirStream, - submissionContext.OperationName, + $"ENTRYPOINT__{submissionContext.OperationName}", new List(), Runtime.Submitters.SubmissionOptions.Default.With(friendlyName: submissionContext.OperationName, shots: 1)); - channel?.Stdout($"Job successfully submitted for {submissionContext.Shots} shots."); + channel?.Stdout($"Job successfully submitted."); channel?.Stdout($" Job name: {submissionContext.FriendlyName}"); channel?.Stdout($" Job ID: {job.Id}"); MostRecentJobId = job.Id; @@ -551,7 +551,10 @@ public async Task GetJobResultAsync(IChannel? channel, string j { var request = WebRequest.Create(job.OutputDataUri); using var responseStream = request.GetResponse().GetResponseStream(); - return responseStream.ToHistogram(Logger).ToExecutionResult(); + return responseStream.ToHistogram( + Logger, + isSimulatorOutput: this.ActiveTarget?.TargetId?.StartsWith(MicrosoftSimulator) ?? false) + .ToExecutionResult(); } catch (Exception e) { diff --git a/src/AzureClient/Visualization/HistogramEncoders.cs b/src/AzureClient/Visualization/HistogramEncoders.cs index c77fbfd3b2..dabe2717e8 100644 --- a/src/AzureClient/Visualization/HistogramEncoders.cs +++ b/src/AzureClient/Visualization/HistogramEncoders.cs @@ -20,9 +20,35 @@ internal class Histogram : Dictionary internal static class HistogramExtensions { - internal static Histogram ToHistogram(this Stream stream, ILogger? logger = null) + internal static Histogram ToHistogram(this Stream stream, ILogger? logger = null, bool isSimulatorOutput = false) { var output = new StreamReader(stream).ReadToEnd(); + if (isSimulatorOutput) + { + // This routine seems to be using what I think may be an older format + // (the az quantum cli had handling for both): {"Histogram":["0",0.5,"1",0.5]} + output = "{ \"Histogram\" : [ \"" + output.Trim() + "\", 1.0 ] }"; + + // TODO: Make this more general. The corresponding implementation from the az quantum cli is: + // + // if job.target.startswith("microsoft.simulator"): + // + // lines = [line.strip() for line in json_file.readlines()] + // result_start_line = len(lines) - 1 + // if lines[-1].endswith('"'): + // while not lines[result_start_line].startswith('"'): + // result_start_line -= 1 + // + // print('\n'.join(lines[:result_start_line])) + // result = ' '.join(lines[result_start_line:])[1:-1] # seems the cleanest version to display + // print("_" * len(result) + "\n") + // + // json_string = "{ \"histogram\" : { \"" + result + "\" : 1 } }" + // data = json.loads(json_string) + // else: + // data = json.load(json_file) + } + var deserializedOutput = JsonConvert.DeserializeObject>(output); var histogram = new Histogram(); From 6eb4d405fd6b8eef9ac1a22b909b56d5e025e19e Mon Sep 17 00:00:00 2001 From: Christopher Granade Date: Fri, 7 Jan 2022 17:30:08 -0800 Subject: [PATCH 11/51] Update to latest package versions. --- .../EntryPoint/EntryPointGenerator.cs | 5 +-- .../EntryPoint/IEntryPointGenerator.cs | 2 +- src/AzureClient/Extensions.cs | 6 +++- src/Core/Compiler/CompilerService.cs | 31 ++++++++++------- src/Core/Compiler/ICompilerService.cs | 2 +- src/Core/Core.csproj | 10 +++--- .../ExecutionPathTracer.csproj | 2 +- .../Mock.Chemistry/Mock.Chemistry.csproj | 4 +-- .../Mock.Standard/Mock.Standard.csproj | 4 +-- .../ProjectA.csproj | 2 +- .../ProjectB.csproj | 2 +- .../Workspace.ProjectReferences.csproj | 4 +-- src/Tool/appsettings.json | 34 +++++++++---------- 13 files changed, 59 insertions(+), 49 deletions(-) diff --git a/src/AzureClient/EntryPoint/EntryPointGenerator.cs b/src/AzureClient/EntryPoint/EntryPointGenerator.cs index b971a10f32..6c5b03abb7 100644 --- a/src/AzureClient/EntryPoint/EntryPointGenerator.cs +++ b/src/AzureClient/EntryPoint/EntryPointGenerator.cs @@ -76,7 +76,7 @@ public EntryPointGenerator( } public IEntryPoint Generate(string operationName, string? executionTarget, - RuntimeCapability? runtimeCapability = null) + RuntimeCapability? runtimeCapability = null, bool forceQir = false) { Logger?.LogDebug($"Generating entry point: operationName={operationName}, executionTarget={executionTarget}"); @@ -148,7 +148,8 @@ public IEntryPoint Generate(string operationName, string? executionTarget, } EntryPointAssemblyInfo = Compiler.BuildEntryPoint( - operationInfo, compilerMetadata, logger, Path.Combine(Workspace.CacheFolder, "__entrypoint__.dll"), executionTarget, runtimeCapability); + operationInfo, compilerMetadata, logger, Path.Combine(Workspace.CacheFolder, "__entrypoint__.dll"), executionTarget, runtimeCapability, + forceQir: forceQir); if (EntryPointAssemblyInfo == null || logger.HasErrors) { Logger?.LogError($"Error compiling entry point for operation {operationName}."); diff --git a/src/AzureClient/EntryPoint/IEntryPointGenerator.cs b/src/AzureClient/EntryPoint/IEntryPointGenerator.cs index 0ead6ecb88..6249abb5d4 100644 --- a/src/AzureClient/EntryPoint/IEntryPointGenerator.cs +++ b/src/AzureClient/EntryPoint/IEntryPointGenerator.cs @@ -42,6 +42,6 @@ public interface IEntryPointGenerator /// The runtime capabilities of the intended execution target. /// The generated entry point. public IEntryPoint Generate(string operationName, string? executionTarget, - RuntimeCapability? runtimeCapabilities = null); + RuntimeCapability? runtimeCapabilities = null, bool forceQir = false); } } diff --git a/src/AzureClient/Extensions.cs b/src/AzureClient/Extensions.cs index 5c48580c81..7950914828 100644 --- a/src/AzureClient/Extensions.cs +++ b/src/AzureClient/Extensions.cs @@ -89,7 +89,11 @@ internal static bool Matches(this CloudJob job, string filter) => (job.Details.Name != null && job.Details.Name.Contains(filter, StringComparison.OrdinalIgnoreCase)) || (job.Details.Target != null && job.Details.Target.Contains(filter, StringComparison.OrdinalIgnoreCase)); - internal static void Log(this Exception ex, IChannel? channel, ILogger? logger, string msg = "") + /// + /// Writes an exception to a logger and emits it to the stderr stream + /// of a Jupyter display channel. + /// + public static void Log(this Exception ex, IChannel? channel, ILogger? logger, string msg = "") { logger?.LogError(ex, msg); channel?.Stderr(msg); diff --git a/src/Core/Compiler/CompilerService.cs b/src/Core/Compiler/CompilerService.cs index 731cfec1fb..baab489807 100644 --- a/src/Core/Compiler/CompilerService.cs +++ b/src/Core/Compiler/CompilerService.cs @@ -151,7 +151,7 @@ public IEnumerable IdentifyElements(string source) /// public AssemblyInfo? BuildEntryPoint(OperationInfo operation, CompilerMetadata metadatas, QSharpLogger logger, string dllName, string? executionTarget = null, - RuntimeCapability? runtimeCapability = null) + RuntimeCapability? runtimeCapability = null, bool forceQir = false) { var signature = operation.Header.PrintSignature(); var argumentTuple = SyntaxTreeToQsharp.ArgumentTuple(operation.Header.ArgumentTuple, type => type.ToString(), symbolsOnly: true); @@ -168,7 +168,7 @@ public IEnumerable IdentifyElements(string source) }}"; var sources = new Dictionary() {{ entryPointUri, entryPointSnippet }}.ToImmutableDictionary(); - return BuildAssembly(sources, metadatas, logger, dllName, compileAsExecutable: true, executionTarget, runtimeCapability, regenerateAll: true); + return BuildAssembly(sources, metadatas, logger, dllName, compileAsExecutable: true, executionTarget, runtimeCapability, regenerateAll: true, forceQir: forceQir); } /// @@ -216,9 +216,16 @@ string WrapInNamespace(Snippet s) => /// /// Builds the corresponding .net core assembly from the Q# syntax tree. /// + /// + /// The resulting assembly info will contain QIR instead of a Q# + /// syntax if is non-null or + /// is set. QIR generation requires at + /// least one valid entry point to be defined. + /// private AssemblyInfo? BuildAssembly(ImmutableDictionary sources, CompilerMetadata metadata, QSharpLogger logger, string dllName, bool compileAsExecutable, string? executionTarget, - RuntimeCapability? runtimeCapability = null, bool regenerateAll = false) + RuntimeCapability? runtimeCapability = null, bool regenerateAll = false, + bool forceQir = false) { logger.LogDebug($"Compiling the following Q# files: {string.Join(",", sources.Keys.Select(f => f.LocalPath))}"); @@ -264,7 +271,7 @@ string WrapInNamespace(Snippet s) => List? manifestResources = null; Stream? qirStream = null; - if (string.IsNullOrEmpty(executionTarget)) + if (string.IsNullOrEmpty(executionTarget) && !forceQir) { // Generate the assembly from the C# compilation: var syntaxTree = new QsCompilation(fromSources.ToImmutableArray(), qsCompilation.EntryPoints); @@ -302,15 +309,13 @@ string WrapInNamespace(Snippet s) => var bcFile = CompilationLoader.GeneratedFile(Path.Combine(tempPath, Path.GetRandomFileName()), tempPath, ".bc", ""); generator.Emit(bcFile, emitBitcode: true); qirStream = File.OpenRead(bcFile); - - manifestResources = new List() - { - new ResourceDescription( - resourceName: DotnetCoreDll.QirResourceName, - dataProvider: () => qirStream, - isPublic: true - ) - }; + } + else if (forceQir) + { + // If we made it here, QIR was enabled, but we didn't have + // any valid entry points. + logger.LogError("IQS006", "QIR generation was enabled, but no entry points were defined."); + return null; } using var ms = new MemoryStream(); diff --git a/src/Core/Compiler/ICompilerService.cs b/src/Core/Compiler/ICompilerService.cs index 746e923f22..2dba509527 100644 --- a/src/Core/Compiler/ICompilerService.cs +++ b/src/Core/Compiler/ICompilerService.cs @@ -25,7 +25,7 @@ public interface ICompilerService /// by the provided object. /// AssemblyInfo BuildEntryPoint(OperationInfo operation, CompilerMetadata metadatas, QSharpLogger logger, string dllName, string executionTarget = null, - RuntimeCapability runtimeCapability = null); + RuntimeCapability runtimeCapability = null, bool forceQir = false); /// /// Builds the corresponding .net core assembly from the code in the given Q# Snippets. diff --git a/src/Core/Core.csproj b/src/Core/Core.csproj index d88b30420c..eb08bb57cc 100644 --- a/src/Core/Core.csproj +++ b/src/Core/Core.csproj @@ -38,11 +38,11 @@ - - - - - + + + + + diff --git a/src/ExecutionPathTracer/ExecutionPathTracer.csproj b/src/ExecutionPathTracer/ExecutionPathTracer.csproj index fc5be105fb..8f1568a6b2 100644 --- a/src/ExecutionPathTracer/ExecutionPathTracer.csproj +++ b/src/ExecutionPathTracer/ExecutionPathTracer.csproj @@ -32,7 +32,7 @@ - + diff --git a/src/MockLibraries/Mock.Chemistry/Mock.Chemistry.csproj b/src/MockLibraries/Mock.Chemistry/Mock.Chemistry.csproj index 25f285cd24..4818a34692 100644 --- a/src/MockLibraries/Mock.Chemistry/Mock.Chemistry.csproj +++ b/src/MockLibraries/Mock.Chemistry/Mock.Chemistry.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 @@ -6,6 +6,6 @@ - + diff --git a/src/MockLibraries/Mock.Standard/Mock.Standard.csproj b/src/MockLibraries/Mock.Standard/Mock.Standard.csproj index 25f285cd24..4818a34692 100644 --- a/src/MockLibraries/Mock.Standard/Mock.Standard.csproj +++ b/src/MockLibraries/Mock.Standard/Mock.Standard.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 @@ -6,6 +6,6 @@ - + diff --git a/src/Tests/Workspace.ProjectReferences.ProjectA/ProjectA.csproj b/src/Tests/Workspace.ProjectReferences.ProjectA/ProjectA.csproj index 4ad401a891..d34d284554 100644 --- a/src/Tests/Workspace.ProjectReferences.ProjectA/ProjectA.csproj +++ b/src/Tests/Workspace.ProjectReferences.ProjectA/ProjectA.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 diff --git a/src/Tests/Workspace.ProjectReferences.ProjectB/ProjectB.csproj b/src/Tests/Workspace.ProjectReferences.ProjectB/ProjectB.csproj index de2f56a308..8c33dd939a 100644 --- a/src/Tests/Workspace.ProjectReferences.ProjectB/ProjectB.csproj +++ b/src/Tests/Workspace.ProjectReferences.ProjectB/ProjectB.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 diff --git a/src/Tests/Workspace.ProjectReferences/Workspace.ProjectReferences.csproj b/src/Tests/Workspace.ProjectReferences/Workspace.ProjectReferences.csproj index f3bff46da9..08846bbcdd 100644 --- a/src/Tests/Workspace.ProjectReferences/Workspace.ProjectReferences.csproj +++ b/src/Tests/Workspace.ProjectReferences/Workspace.ProjectReferences.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 @@ -7,7 +7,7 @@ - + diff --git a/src/Tool/appsettings.json b/src/Tool/appsettings.json index 62bb2c976b..1bfd2d8982 100644 --- a/src/Tool/appsettings.json +++ b/src/Tool/appsettings.json @@ -6,22 +6,22 @@ }, "AllowedHosts": "*", "DefaultPackageVersions": [ - "Microsoft.Quantum.Compiler::0.18.210729377-pull", - "Microsoft.Quantum.CSharpGeneration::0.18.210729377-pull", - "Microsoft.Quantum.Development.Kit::0.18.210729377-pull", - "Microsoft.Quantum.Simulators::0.18.210729377-pull", - "Microsoft.Quantum.Xunit::0.18.210729377-pull", - "Microsoft.Quantum.Standard::0.18.210729377-pull", - "Microsoft.Quantum.Standard.Visualization::0.18.210729377-pull", - "Microsoft.Quantum.Chemistry::0.18.210729377-pull", - "Microsoft.Quantum.Chemistry.Jupyter::0.18.210729377-pull", - "Microsoft.Quantum.MachineLearning::0.18.210729377-pull", - "Microsoft.Quantum.Numerics::0.18.210729377-pull", - "Microsoft.Quantum.Katas::0.18.210729377-pull", - "Microsoft.Quantum.Research::0.18.210729377-pull", - "Microsoft.Quantum.Providers.IonQ::0.18.2107150698-alpha", - "Microsoft.Quantum.Providers.Honeywell::0.18.2107150698-alpha", - "Microsoft.Quantum.Providers.QCI::0.18.2107150698-alpha", - "Microsoft.Quantum.Providers.Core::0.18.2107150698-alpha" + "Microsoft.Quantum.Compiler::0.21.2112180703", + "Microsoft.Quantum.CSharpGeneration::0.21.2112180703", + "Microsoft.Quantum.Development.Kit::0.21.2112180703", + "Microsoft.Quantum.Simulators::0.21.2112180703", + "Microsoft.Quantum.Xunit::0.21.2112180703", + "Microsoft.Quantum.Standard::0.21.2112180703", + "Microsoft.Quantum.Standard.Visualization::0.21.2112180703", + "Microsoft.Quantum.Chemistry::0.21.2112180703", + "Microsoft.Quantum.Chemistry.Jupyter::0.21.2112180703", + "Microsoft.Quantum.MachineLearning::0.21.2112180703", + "Microsoft.Quantum.Numerics::0.21.2112180703", + "Microsoft.Quantum.Katas::0.21.2112180703", + "Microsoft.Quantum.Research::0.21.2112180703", + "Microsoft.Quantum.Providers.IonQ::0.21.2112180703", + "Microsoft.Quantum.Providers.Honeywell::0.21.2112180703", + "Microsoft.Quantum.Providers.QCI::0.21.2112180703", + "Microsoft.Quantum.Providers.Core::0.21.2112180703" ] } \ No newline at end of file From 7eb1d0da2cd15633ad2a2591f4305e61e6b3606f Mon Sep 17 00:00:00 2001 From: Christopher Granade Date: Fri, 7 Jan 2022 17:30:16 -0800 Subject: [PATCH 12/51] Add new %qir magic. --- src/Kernel/Magic/QirMagic.cs | 111 +++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 src/Kernel/Magic/QirMagic.cs diff --git a/src/Kernel/Magic/QirMagic.cs b/src/Kernel/Magic/QirMagic.cs new file mode 100644 index 0000000000..8fe9291eda --- /dev/null +++ b/src/Kernel/Magic/QirMagic.cs @@ -0,0 +1,111 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Diagnostics; +using System.IO; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Microsoft.Jupyter.Core; +using Microsoft.Quantum.IQSharp.AzureClient; +using Microsoft.Quantum.IQSharp.Common; +using Microsoft.Quantum.IQSharp.Jupyter; +using Microsoft.Quantum.IQSharp.Kernel; +using Microsoft.Quantum.QsCompiler; +using Microsoft.Quantum.Simulation.Core; +using Microsoft.Quantum.Simulation.Simulators; + +namespace Microsoft.Quantum.IQSharp.Kernel +{ + /// + /// A magic command that can be used to generate QIR from a given + /// operation as an entry point. + /// + public class QirMagic : AbstractMagic + { + private const string ParameterNameOperationName = "__operationName__"; + private const string ParameterNameOutputPath = "output"; + + public QirMagic(ISymbolResolver resolver, IEntryPointGenerator entryPointGenerator, ILogger logger) : base( + "qir", + new Microsoft.Jupyter.Core.Documentation + { + Summary = "TODO.", + Description = @" + TODO + + #### Required parameters + + - Q# operation or function name. This must be the first parameter, and must be a valid Q# operation + or function name that has been defined either in the notebook or in a Q# file in the same folder. + ".Dedent(), + Examples = new [] + { + @" + TODO + ".Dedent() + } + }, logger) + { + this.EntryPointGenerator = entryPointGenerator; + this.Logger = logger; + } + + private ILogger? Logger { get; } + + // TODO: EntryPointGenerator might should move out of the Azure Client + // project. + public IEntryPointGenerator EntryPointGenerator { 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 inputParameters = ParseInputParameters(input, firstParameterInferredName: ParameterNameOperationName); + + var name = inputParameters.DecodeParameter(ParameterNameOperationName); + var output = inputParameters.DecodeParameter(ParameterNameOutputPath); + + IEntryPoint? entryPoint; + try + { + entryPoint = EntryPointGenerator.Generate(name, null, RuntimeCapability.FullComputation, forceQir: true); + } + catch (TaskCanceledException tce) + { + throw tce; + } + catch (CompilationErrorsException e) + { + e.Log(channel, this.Logger, $"The Q# operation {name} could not be compiled as an entry point for job execution."); + foreach (var message in e.Errors) channel?.Stderr(message); + return AzureClientError.InvalidEntryPoint.ToExecutionResult(); + } + + if (entryPoint == null) + { + return "Internal error: generated entry point was null, but no compilation errors were returned." + .ToExecutionResult(ExecuteStatus.Error); + } + + if (entryPoint.QirStream == null) + { + return "Internal error: generated entry point does not contain a QIR bitcode stream, but no compilation errors were returned." + .ToExecutionResult(ExecuteStatus.Error); + } + + using (var outStream = File.OpenWrite(output)) + { + entryPoint.QirStream.CopyTo(outStream); + } + + return ExecuteStatus.Ok.ToExecutionResult(); + } + } +} From 3430a904a02e791b1f3537da299db7577b59ca5b Mon Sep 17 00:00:00 2001 From: Christopher Granade Date: Fri, 14 Jan 2022 14:42:29 -0800 Subject: [PATCH 13/51] Add Python support for new %qir command. --- .../qsharp-core/qsharp/clients/iqsharp.py | 3 ++ src/Python/qsharp-core/qsharp/loader.py | 29 +++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/src/Python/qsharp-core/qsharp/clients/iqsharp.py b/src/Python/qsharp-core/qsharp/clients/iqsharp.py index 173b2f1b39..ee14dc57b5 100644 --- a/src/Python/qsharp-core/qsharp/clients/iqsharp.py +++ b/src/Python/qsharp-core/qsharp/clients/iqsharp.py @@ -195,6 +195,9 @@ def estimate(self, op, **kwargs) -> Dict[str, int]: def trace(self, op, **kwargs) -> Any: return self._execute_callable_magic('trace', op, _quiet_ = True, **kwargs) + def compile_to_qir(self, op, output: str) -> None: + return self._execute_callable_magic('qir', op, output=output) + def component_versions(self, **kwargs) -> Dict[str, LooseVersion]: """ Returns a dictionary from components of the IQ# kernel to their diff --git a/src/Python/qsharp-core/qsharp/loader.py b/src/Python/qsharp-core/qsharp/loader.py index 13a71d4713..3ad933428f 100644 --- a/src/Python/qsharp-core/qsharp/loader.py +++ b/src/Python/qsharp-core/qsharp/loader.py @@ -7,14 +7,27 @@ # Licensed under the MIT License. ## +import os import sys from types import ModuleType, new_class import importlib from importlib.abc import MetaPathFinder, Loader +import tempfile as tf + import qsharp from typing import Iterable, List, Optional, Any, Dict, Tuple +try: + import pyqir_parser as pqp +except ImportError as ex: + try: + import pyqir.parser as pqp + except ImportError: + class pqp: + failed_with = ex + QirModule = None + import logging logger = logging.getLogger(__name__) @@ -107,6 +120,22 @@ def trace(self, **kwargs) -> Any: """ return qsharp.client.trace(self, **kwargs) + def as_qir(self) -> pqp.QirModule: + if getattr(pqp, "failed_with", None) is not None: + raise pqp.failed_with + + # NB: Cannot load directly from bytes due to a missing feature in + # the llvm-ir crate that causes a similarly missing feature in + # pyqir.parser. + f = tf.NamedTemporaryFile(delete=False, suffix='.bc') + f.close() + bitcode = qsharp.client.compile_to_qir(self, output=f.name) + module = pqp.QirModule(f.name) + try: + os.unlink(f.name) + except: + pass + return module class QSharpModule(ModuleType): _qs_name : str From 2d0a8bb32f8a05e0c6a659d7950dcd8d2073b5b8 Mon Sep 17 00:00:00 2001 From: Scott Carda Date: Wed, 23 Feb 2022 16:21:32 -0800 Subject: [PATCH 14/51] Added a SubmitAsync for the submitter object. --- src/AzureClient/EntryPoint/EntryPoint.cs | 37 ++++++++++++++++++++--- src/AzureClient/EntryPoint/IEntryPoint.cs | 5 ++- 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/src/AzureClient/EntryPoint/EntryPoint.cs b/src/AzureClient/EntryPoint/EntryPoint.cs index 370a188f40..5bdfc2b46a 100644 --- a/src/AzureClient/EntryPoint/EntryPoint.cs +++ b/src/AzureClient/EntryPoint/EntryPoint.cs @@ -10,6 +10,7 @@ using System.Threading.Tasks; using Microsoft.Quantum.IQSharp.Jupyter; using Microsoft.Quantum.Runtime; +using Microsoft.Quantum.Runtime.Submitters; using Microsoft.Quantum.Simulation.Core; namespace Microsoft.Quantum.IQSharp.AzureClient @@ -21,7 +22,7 @@ internal class EntryPoint : IEntryPoint private Type InputType { get; } private Type OutputType { get; } private OperationInfo OperationInfo { get; } - public Stream? QirStream { get; } + public Stream QirStream { get; } /// /// Creates an object used to submit jobs to Azure Quantum. @@ -36,7 +37,7 @@ internal class EntryPoint : IEntryPoint /// /// Stream from which QIR bitcode for the entry point can be read. /// - public EntryPoint(object entryPointInfo, Type inputType, Type outputType, OperationInfo operationInfo, Stream? qirStream) + public EntryPoint(object entryPointInfo, Type inputType, Type outputType, OperationInfo operationInfo, Stream qirStream) { EntryPointInfo = entryPointInfo; InputType = inputType; @@ -45,8 +46,7 @@ public EntryPoint(object entryPointInfo, Type inputType, Type outputType, Operat QirStream = qirStream; } - /// - public Task SubmitAsync(IQuantumMachine machine, AzureSubmissionContext submissionContext) + private object GetEntryPointInput(AzureSubmissionContext submissionContext) { var parameterTypes = new List(); var parameterValues = new List(); @@ -74,12 +74,18 @@ public Task SubmitAsync(IQuantumMachine machine, AzureSubmis } } - var entryPointInput = parameterValues.Count switch + return parameterValues.Count switch { 0 => QVoid.Instance, 1 => parameterValues.Single(), _ => InputType.GetConstructor(parameterTypes.ToArray()).Invoke(parameterValues.ToArray()) }; + } + + /// + public Task SubmitAsync(IQuantumMachine machine, AzureSubmissionContext submissionContext) + { + var entryPointInput = GetEntryPointInput(submissionContext); // Find and invoke the method on IQuantumMachine that is declared as: // Task SubmitAsync(EntryPointInfo info, TInput input, SubmissionContext context) @@ -96,5 +102,26 @@ public Task SubmitAsync(IQuantumMachine machine, AzureSubmis var submitParameters = new object[] { EntryPointInfo, entryPointInput, submissionContext }; return (Task)submitMethod.Invoke(machine, submitParameters); } + + public Task SubmitAsync(IQSharpSubmitter submitter, AzureSubmissionContext submissionContext) + { + var entryPointInput = GetEntryPointInput(submissionContext); + + // Find and invoke the method on IQuantumMachine that is declared as: + // Task SubmitAsync(EntryPointInfo info, TInput input, SubmissionContext context, Stream qirStream) + var submitMethod = typeof(IQuantumMachine) + .GetMethods() + .Single(method => + method.Name == "SubmitAsync" + && method.IsGenericMethodDefinition + && method.GetParameters().Length == 4 + && method.GetParameters()[0].ParameterType.GetGenericTypeDefinition() == EntryPointInfo.GetType().GetGenericTypeDefinition() + && method.GetParameters()[1].ParameterType.IsGenericMethodParameter + && method.GetParameters()[2].ParameterType == typeof(IQuantumMachineSubmissionContext) + && method.GetParameters()[3].ParameterType == typeof(Stream)) + .MakeGenericMethod(new Type[] { InputType, OutputType }); + var submitParameters = new object[] { EntryPointInfo, entryPointInput, submissionContext, QirStream }; + return (Task)submitMethod.Invoke(submitter, submitParameters); + } } } diff --git a/src/AzureClient/EntryPoint/IEntryPoint.cs b/src/AzureClient/EntryPoint/IEntryPoint.cs index 61bb21635a..4364c1af60 100644 --- a/src/AzureClient/EntryPoint/IEntryPoint.cs +++ b/src/AzureClient/EntryPoint/IEntryPoint.cs @@ -9,6 +9,7 @@ using System.Text; using System.Threading.Tasks; using Microsoft.Quantum.Runtime; +using Microsoft.Quantum.Runtime.Submitters; namespace Microsoft.Quantum.IQSharp.AzureClient { @@ -26,6 +27,8 @@ public interface IEntryPoint /// The details of the submitted job. public Task SubmitAsync(IQuantumMachine machine, AzureSubmissionContext submissionContext); - public Stream? QirStream { get; } + public Task SubmitAsync(IQSharpSubmitter submitter, AzureSubmissionContext submissionContext); + + public Stream QirStream { get; } } } From f2505d92d3beb7ec6f2faf783d307a121f2fd85b Mon Sep 17 00:00:00 2001 From: Scott Carda Date: Tue, 1 Mar 2022 13:20:35 -0800 Subject: [PATCH 15/51] Change from QSharpSubmitter handle to QirSubmitter handle. --- src/AzureClient/AzureClient.cs | 11 +-- src/AzureClient/EntryPoint/EntryPoint.cs | 87 +++++++++++++++++++---- src/AzureClient/EntryPoint/IEntryPoint.cs | 2 +- 3 files changed, 82 insertions(+), 18 deletions(-) diff --git a/src/AzureClient/AzureClient.cs b/src/AzureClient/AzureClient.cs index ae6f4ff8ca..4b6c7cfeb0 100644 --- a/src/AzureClient/AzureClient.cs +++ b/src/AzureClient/AzureClient.cs @@ -349,11 +349,12 @@ private async Task SubmitOrExecuteJobAsync( //channel?.Stdout(reader.ReadToEnd()); //entryPoint.QirStream.Seek(0, SeekOrigin.Begin); - var job = await submitter.SubmitAsync( - entryPoint.QirStream, - $"ENTRYPOINT__{submissionContext.OperationName}", - new List(), - Runtime.Submitters.SubmissionOptions.Default.With(friendlyName: submissionContext.OperationName, shots: 1)); + //var job = await submitter.SubmitAsync( + // entryPoint.QirStream, + // $"ENTRYPOINT__{submissionContext.OperationName}", + // new List(), + // Runtime.Submitters.SubmissionOptions.Default.With(friendlyName: submissionContext.OperationName, shots: 1)); + var job = await entryPoint.SubmitAsync(submitter, submissionContext); channel?.Stdout($"Job successfully submitted."); channel?.Stdout($" Job name: {submissionContext.FriendlyName}"); channel?.Stdout($" Job ID: {job.Id}"); diff --git a/src/AzureClient/EntryPoint/EntryPoint.cs b/src/AzureClient/EntryPoint/EntryPoint.cs index 5bdfc2b46a..9cf3d77567 100644 --- a/src/AzureClient/EntryPoint/EntryPoint.cs +++ b/src/AzureClient/EntryPoint/EntryPoint.cs @@ -46,7 +46,7 @@ public EntryPoint(object entryPointInfo, Type inputType, Type outputType, Operat QirStream = qirStream; } - private object GetEntryPointInput(AzureSubmissionContext submissionContext) + private object GetEntryPointInputObject(AzureSubmissionContext submissionContext) { var parameterTypes = new List(); var parameterValues = new List(); @@ -82,10 +82,70 @@ private object GetEntryPointInput(AzureSubmissionContext submissionContext) }; } + private ArgumentValue GetArgumentValue(string parameterValue, System.Reflection.ParameterInfo parameter) + { + var parameterType = parameter.ParameterType; + + if (parameterType == typeof(bool)) + { + return new ArgumentValue.Bool(Newtonsoft.Json.JsonConvert.DeserializeObject(parameterValue)); + } + else if (parameterType == typeof(double)) + { + return new ArgumentValue.Double(Newtonsoft.Json.JsonConvert.DeserializeObject(parameterValue)); + } + else if (parameterType == typeof(long)) + { + return new ArgumentValue.Int(Newtonsoft.Json.JsonConvert.DeserializeObject(parameterValue)); + } + else if (parameterType == typeof(string)) + { + return new ArgumentValue.String(parameterValue); + } + else if (parameterType == typeof(Pauli)) + { + return new ArgumentValue.Pauli(Newtonsoft.Json.JsonConvert.DeserializeObject(parameterValue)); + } + else if (parameterType == typeof(Result)) + { + return new ArgumentValue.Result(Newtonsoft.Json.JsonConvert.DeserializeObject(parameterValue)); + } + else + { + throw new ArgumentException($"The given type of {parameterType.Name} is not supported."); ; + } + } + + private IReadOnlyList GetEntryPointInputArguments(AzureSubmissionContext submissionContext) + { + var argumentList = new List(); + foreach (var parameter in OperationInfo.RoslynParameters) + { + if (!submissionContext.InputParameters.ContainsKey(parameter.Name)) + { + throw new ArgumentException($"Required parameter {parameter.Name} was not specified."); + } + + string rawParameterValue = submissionContext.InputParameters[parameter.Name]; + + try + { + var argument = new Argument(parameter.Name, GetArgumentValue(rawParameterValue, parameter)); + argumentList.Add(argument); + } + catch (Exception e) + { + throw new ArgumentException($"The value {rawParameterValue} provided for parameter {parameter.Name} could not be converted to the expected type: {e.Message}"); + } + } + + return argumentList; + } + /// public Task SubmitAsync(IQuantumMachine machine, AzureSubmissionContext submissionContext) { - var entryPointInput = GetEntryPointInput(submissionContext); + var entryPointInput = GetEntryPointInputObject(submissionContext); // Find and invoke the method on IQuantumMachine that is declared as: // Task SubmitAsync(EntryPointInfo info, TInput input, SubmissionContext context) @@ -103,24 +163,27 @@ public Task SubmitAsync(IQuantumMachine machine, AzureSubmis return (Task)submitMethod.Invoke(machine, submitParameters); } - public Task SubmitAsync(IQSharpSubmitter submitter, AzureSubmissionContext submissionContext) + public Task SubmitAsync(IQirSubmitter submitter, AzureSubmissionContext submissionContext) { - var entryPointInput = GetEntryPointInput(submissionContext); + var entryPointInput = GetEntryPointInputArguments(submissionContext); + + var options = SubmissionOptions.Default; + options = options.With(submissionContext.FriendlyName, submissionContext.Shots, submissionContext.InputParams); + // ToDo: update this comment // Find and invoke the method on IQuantumMachine that is declared as: // Task SubmitAsync(EntryPointInfo info, TInput input, SubmissionContext context, Stream qirStream) - var submitMethod = typeof(IQuantumMachine) + var submitMethod = typeof(IQirSubmitter) .GetMethods() .Single(method => method.Name == "SubmitAsync" - && method.IsGenericMethodDefinition && method.GetParameters().Length == 4 - && method.GetParameters()[0].ParameterType.GetGenericTypeDefinition() == EntryPointInfo.GetType().GetGenericTypeDefinition() - && method.GetParameters()[1].ParameterType.IsGenericMethodParameter - && method.GetParameters()[2].ParameterType == typeof(IQuantumMachineSubmissionContext) - && method.GetParameters()[3].ParameterType == typeof(Stream)) - .MakeGenericMethod(new Type[] { InputType, OutputType }); - var submitParameters = new object[] { EntryPointInfo, entryPointInput, submissionContext, QirStream }; + && method.GetParameters()[0].ParameterType == typeof(Stream) + && method.GetParameters()[1].ParameterType == typeof(string) + && method.GetParameters()[2].ParameterType == typeof(IReadOnlyList) + && method.GetParameters()[3].ParameterType == typeof(SubmissionOptions) + ); + var submitParameters = new object[] { QirStream, $"ENTRYPOINT__{submissionContext.OperationName}", entryPointInput, options }; return (Task)submitMethod.Invoke(submitter, submitParameters); } } diff --git a/src/AzureClient/EntryPoint/IEntryPoint.cs b/src/AzureClient/EntryPoint/IEntryPoint.cs index 4364c1af60..fc3620d527 100644 --- a/src/AzureClient/EntryPoint/IEntryPoint.cs +++ b/src/AzureClient/EntryPoint/IEntryPoint.cs @@ -27,7 +27,7 @@ public interface IEntryPoint /// The details of the submitted job. public Task SubmitAsync(IQuantumMachine machine, AzureSubmissionContext submissionContext); - public Task SubmitAsync(IQSharpSubmitter submitter, AzureSubmissionContext submissionContext); + public Task SubmitAsync(IQirSubmitter submitter, AzureSubmissionContext submissionContext); public Stream QirStream { get; } } From ae6b3dd9a36f7f5f05028be95225c62d36cad658 Mon Sep 17 00:00:00 2001 From: Scott Carda Date: Tue, 1 Mar 2022 14:45:41 -0800 Subject: [PATCH 16/51] updated version number --- src/AzureClient/EntryPoint/EntryPoint.cs | 2 +- src/Core/Core.csproj | 10 +++--- .../ExecutionPathTracer.csproj | 2 +- .../Mock.Chemistry/Mock.Chemistry.csproj | 4 +-- .../Mock.Standard/Mock.Standard.csproj | 4 +-- .../ProjectA.csproj | 2 +- .../ProjectB.csproj | 2 +- .../Workspace.ProjectReferences.csproj | 4 +-- src/Tool/appsettings.json | 34 +++++++++---------- 9 files changed, 32 insertions(+), 32 deletions(-) diff --git a/src/AzureClient/EntryPoint/EntryPoint.cs b/src/AzureClient/EntryPoint/EntryPoint.cs index 22f008aa79..194fbbe5c0 100644 --- a/src/AzureClient/EntryPoint/EntryPoint.cs +++ b/src/AzureClient/EntryPoint/EntryPoint.cs @@ -41,7 +41,7 @@ internal class EntryPoint : IEntryPoint /// Stream from which QIR bitcode for the entry point can be read. /// /// Logger used to report internal diagnostics. - public EntryPoint(object entryPointInfo, Type inputType, Type outputType, OperationInfo operationInfo, , Stream qirStream, ILogger? logger) + public EntryPoint(object entryPointInfo, Type inputType, Type outputType, OperationInfo operationInfo, Stream qirStream, ILogger? logger) { EntryPointInfo = entryPointInfo; InputType = inputType; diff --git a/src/Core/Core.csproj b/src/Core/Core.csproj index ec01ca2593..6dba359667 100644 --- a/src/Core/Core.csproj +++ b/src/Core/Core.csproj @@ -38,11 +38,11 @@ - - - - - + + + + + diff --git a/src/ExecutionPathTracer/ExecutionPathTracer.csproj b/src/ExecutionPathTracer/ExecutionPathTracer.csproj index 64cd72a115..e5df3dff11 100644 --- a/src/ExecutionPathTracer/ExecutionPathTracer.csproj +++ b/src/ExecutionPathTracer/ExecutionPathTracer.csproj @@ -32,7 +32,7 @@ - + diff --git a/src/MockLibraries/Mock.Chemistry/Mock.Chemistry.csproj b/src/MockLibraries/Mock.Chemistry/Mock.Chemistry.csproj index 1f2b1185ca..27002f4179 100644 --- a/src/MockLibraries/Mock.Chemistry/Mock.Chemistry.csproj +++ b/src/MockLibraries/Mock.Chemistry/Mock.Chemistry.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 @@ -6,6 +6,6 @@ - + diff --git a/src/MockLibraries/Mock.Standard/Mock.Standard.csproj b/src/MockLibraries/Mock.Standard/Mock.Standard.csproj index 1f2b1185ca..27002f4179 100644 --- a/src/MockLibraries/Mock.Standard/Mock.Standard.csproj +++ b/src/MockLibraries/Mock.Standard/Mock.Standard.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 @@ -6,6 +6,6 @@ - + diff --git a/src/Tests/Workspace.ProjectReferences.ProjectA/ProjectA.csproj b/src/Tests/Workspace.ProjectReferences.ProjectA/ProjectA.csproj index b56d7e3f8c..12ee0ffadd 100644 --- a/src/Tests/Workspace.ProjectReferences.ProjectA/ProjectA.csproj +++ b/src/Tests/Workspace.ProjectReferences.ProjectA/ProjectA.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 diff --git a/src/Tests/Workspace.ProjectReferences.ProjectB/ProjectB.csproj b/src/Tests/Workspace.ProjectReferences.ProjectB/ProjectB.csproj index f8c0a6c431..69a9a27953 100644 --- a/src/Tests/Workspace.ProjectReferences.ProjectB/ProjectB.csproj +++ b/src/Tests/Workspace.ProjectReferences.ProjectB/ProjectB.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 diff --git a/src/Tests/Workspace.ProjectReferences/Workspace.ProjectReferences.csproj b/src/Tests/Workspace.ProjectReferences/Workspace.ProjectReferences.csproj index 0547d2fdab..9ddf3e5656 100644 --- a/src/Tests/Workspace.ProjectReferences/Workspace.ProjectReferences.csproj +++ b/src/Tests/Workspace.ProjectReferences/Workspace.ProjectReferences.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 @@ -7,7 +7,7 @@ - + diff --git a/src/Tool/appsettings.json b/src/Tool/appsettings.json index a4be6a05e3..c1fcd918da 100644 --- a/src/Tool/appsettings.json +++ b/src/Tool/appsettings.json @@ -6,22 +6,22 @@ }, "AllowedHosts": "*", "DefaultPackageVersions": [ - "Microsoft.Quantum.Compiler::0.22.191200-beta", - "Microsoft.Quantum.CSharpGeneration::0.22.191200-beta", - "Microsoft.Quantum.Development.Kit::0.22.191200-beta", - "Microsoft.Quantum.Simulators::0.22.191200-beta", - "Microsoft.Quantum.Xunit::0.22.191200-beta", - "Microsoft.Quantum.Standard::0.22.191200-beta", - "Microsoft.Quantum.Standard.Visualization::0.22.191200-beta", - "Microsoft.Quantum.Chemistry::0.22.191200-beta", - "Microsoft.Quantum.Chemistry.Jupyter::0.22.191200-beta", - "Microsoft.Quantum.MachineLearning::0.22.191200-beta", - "Microsoft.Quantum.Numerics::0.22.191200-beta", - "Microsoft.Quantum.Katas::0.22.191200-beta", - "Microsoft.Quantum.Research::0.22.191200-beta", - "Microsoft.Quantum.Providers.IonQ::0.22.191200-beta", - "Microsoft.Quantum.Providers.Honeywell::0.22.191200-beta", - "Microsoft.Quantum.Providers.QCI::0.22.191200-beta", - "Microsoft.Quantum.Providers.Core::0.22.191200-beta" + "Microsoft.Quantum.Compiler::0.23.195716-beta", + "Microsoft.Quantum.CSharpGeneration::0.23.195716-beta", + "Microsoft.Quantum.Development.Kit::0.23.195716-beta", + "Microsoft.Quantum.Simulators::0.23.195716-beta", + "Microsoft.Quantum.Xunit::0.23.195716-beta", + "Microsoft.Quantum.Standard::0.23.195716-beta", + "Microsoft.Quantum.Standard.Visualization::0.23.195716-beta", + "Microsoft.Quantum.Chemistry::0.23.195716-beta", + "Microsoft.Quantum.Chemistry.Jupyter::0.23.195716-beta", + "Microsoft.Quantum.MachineLearning::0.23.195716-beta", + "Microsoft.Quantum.Numerics::0.23.195716-beta", + "Microsoft.Quantum.Katas::0.23.195716-beta", + "Microsoft.Quantum.Research::0.23.195716-beta", + "Microsoft.Quantum.Providers.IonQ::0.23.195716-beta", + "Microsoft.Quantum.Providers.Honeywell::0.23.195716-beta", + "Microsoft.Quantum.Providers.QCI::0.23.195716-beta", + "Microsoft.Quantum.Providers.Core::0.23.195716-beta" ] } \ No newline at end of file From 449971b2069adced9506203b3d3aa2bb758fc147 Mon Sep 17 00:00:00 2001 From: Scott Carda Date: Tue, 1 Mar 2022 14:53:49 -0800 Subject: [PATCH 17/51] updated comment --- src/AzureClient/EntryPoint/EntryPoint.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/AzureClient/EntryPoint/EntryPoint.cs b/src/AzureClient/EntryPoint/EntryPoint.cs index 194fbbe5c0..726c4f1ec3 100644 --- a/src/AzureClient/EntryPoint/EntryPoint.cs +++ b/src/AzureClient/EntryPoint/EntryPoint.cs @@ -184,9 +184,8 @@ public Task SubmitAsync(IQirSubmitter submitter, AzureSubmis var options = SubmissionOptions.Default; options = options.With(submissionContext.FriendlyName, submissionContext.Shots, submissionContext.InputParams); - // ToDo: update this comment - // Find and invoke the method on IQuantumMachine that is declared as: - // Task SubmitAsync(EntryPointInfo info, TInput input, SubmissionContext context, Stream qirStream) + // Find and invoke the method on IQirSubmitter that is declared as: + // Task SubmitAsync(Stream qir, string entryPoint, IReadOnlyList arguments, SubmissionOptions submissionOptions) var submitMethod = typeof(IQirSubmitter) .GetMethods() .Single(method => From 805cd74fef11a44aea584d9acf48bebe7121fd46 Mon Sep 17 00:00:00 2001 From: Scott Carda Date: Thu, 3 Mar 2022 18:33:33 -0800 Subject: [PATCH 18/51] updated QDK version --- src/AzureClient/Mocks/MockQIRSubmitter.cs | 44 +++++++++++++++++++ src/Core/Core.csproj | 10 ++--- .../ExecutionPathTracer.csproj | 2 +- .../Mock.Chemistry/Mock.Chemistry.csproj | 4 +- .../Mock.Standard/Mock.Standard.csproj | 4 +- .../ProjectA.csproj | 2 +- .../ProjectB.csproj | 2 +- .../Workspace.ProjectReferences.csproj | 4 +- src/Tool/appsettings.json | 34 +++++++------- 9 files changed, 75 insertions(+), 31 deletions(-) create mode 100644 src/AzureClient/Mocks/MockQIRSubmitter.cs diff --git a/src/AzureClient/Mocks/MockQIRSubmitter.cs b/src/AzureClient/Mocks/MockQIRSubmitter.cs new file mode 100644 index 0000000000..480319b016 --- /dev/null +++ b/src/AzureClient/Mocks/MockQIRSubmitter.cs @@ -0,0 +1,44 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#nullable enable + +using System; +using System.Reflection; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Quantum.Runtime; +using Microsoft.Quantum.Simulation.Core; +using Microsoft.Quantum.Runtime.Submitters; +using System.IO; +using System.Collections.Generic; + +namespace Microsoft.Quantum.IQSharp.AzureClient +{ + internal class MockQIRSubmitter : IQirSubmitter + { + public string Target => throw new NotImplementedException(); + + private IReadOnlyList Arguments = new List(); + + public MockQIRSubmitter(IReadOnlyList arguments) + { + this.Arguments = arguments; + } + + public Task SubmitAsync(Stream qir, string entryPoint, IReadOnlyList arguments, SubmissionOptions options) + { + var job = new MockCloudJob(); + MockAzureWorkspace.MockJobIds = new string[] { job.Id }; + + + + return Task.FromResult(job as IQuantumMachineJob); + } + + public string? Validate(Stream qir, string entryPoint, IReadOnlyList arguments) + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/src/Core/Core.csproj b/src/Core/Core.csproj index 6dba359667..a7eb2647bc 100644 --- a/src/Core/Core.csproj +++ b/src/Core/Core.csproj @@ -38,11 +38,11 @@ - - - - - + + + + + diff --git a/src/ExecutionPathTracer/ExecutionPathTracer.csproj b/src/ExecutionPathTracer/ExecutionPathTracer.csproj index e5df3dff11..890374697d 100644 --- a/src/ExecutionPathTracer/ExecutionPathTracer.csproj +++ b/src/ExecutionPathTracer/ExecutionPathTracer.csproj @@ -32,7 +32,7 @@ - + diff --git a/src/MockLibraries/Mock.Chemistry/Mock.Chemistry.csproj b/src/MockLibraries/Mock.Chemistry/Mock.Chemistry.csproj index 27002f4179..23e50e7d7e 100644 --- a/src/MockLibraries/Mock.Chemistry/Mock.Chemistry.csproj +++ b/src/MockLibraries/Mock.Chemistry/Mock.Chemistry.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 @@ -6,6 +6,6 @@ - + diff --git a/src/MockLibraries/Mock.Standard/Mock.Standard.csproj b/src/MockLibraries/Mock.Standard/Mock.Standard.csproj index 27002f4179..23e50e7d7e 100644 --- a/src/MockLibraries/Mock.Standard/Mock.Standard.csproj +++ b/src/MockLibraries/Mock.Standard/Mock.Standard.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 @@ -6,6 +6,6 @@ - + diff --git a/src/Tests/Workspace.ProjectReferences.ProjectA/ProjectA.csproj b/src/Tests/Workspace.ProjectReferences.ProjectA/ProjectA.csproj index 12ee0ffadd..2e1d6a49c5 100644 --- a/src/Tests/Workspace.ProjectReferences.ProjectA/ProjectA.csproj +++ b/src/Tests/Workspace.ProjectReferences.ProjectA/ProjectA.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 diff --git a/src/Tests/Workspace.ProjectReferences.ProjectB/ProjectB.csproj b/src/Tests/Workspace.ProjectReferences.ProjectB/ProjectB.csproj index 69a9a27953..5a062d77a9 100644 --- a/src/Tests/Workspace.ProjectReferences.ProjectB/ProjectB.csproj +++ b/src/Tests/Workspace.ProjectReferences.ProjectB/ProjectB.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 diff --git a/src/Tests/Workspace.ProjectReferences/Workspace.ProjectReferences.csproj b/src/Tests/Workspace.ProjectReferences/Workspace.ProjectReferences.csproj index 9ddf3e5656..0db82b8abf 100644 --- a/src/Tests/Workspace.ProjectReferences/Workspace.ProjectReferences.csproj +++ b/src/Tests/Workspace.ProjectReferences/Workspace.ProjectReferences.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 @@ -7,7 +7,7 @@ - + diff --git a/src/Tool/appsettings.json b/src/Tool/appsettings.json index c1fcd918da..2cb3be429e 100644 --- a/src/Tool/appsettings.json +++ b/src/Tool/appsettings.json @@ -6,22 +6,22 @@ }, "AllowedHosts": "*", "DefaultPackageVersions": [ - "Microsoft.Quantum.Compiler::0.23.195716-beta", - "Microsoft.Quantum.CSharpGeneration::0.23.195716-beta", - "Microsoft.Quantum.Development.Kit::0.23.195716-beta", - "Microsoft.Quantum.Simulators::0.23.195716-beta", - "Microsoft.Quantum.Xunit::0.23.195716-beta", - "Microsoft.Quantum.Standard::0.23.195716-beta", - "Microsoft.Quantum.Standard.Visualization::0.23.195716-beta", - "Microsoft.Quantum.Chemistry::0.23.195716-beta", - "Microsoft.Quantum.Chemistry.Jupyter::0.23.195716-beta", - "Microsoft.Quantum.MachineLearning::0.23.195716-beta", - "Microsoft.Quantum.Numerics::0.23.195716-beta", - "Microsoft.Quantum.Katas::0.23.195716-beta", - "Microsoft.Quantum.Research::0.23.195716-beta", - "Microsoft.Quantum.Providers.IonQ::0.23.195716-beta", - "Microsoft.Quantum.Providers.Honeywell::0.23.195716-beta", - "Microsoft.Quantum.Providers.QCI::0.23.195716-beta", - "Microsoft.Quantum.Providers.Core::0.23.195716-beta" + "Microsoft.Quantum.Compiler::0.23.195983", + "Microsoft.Quantum.CSharpGeneration::0.23.195983", + "Microsoft.Quantum.Development.Kit::0.23.195983", + "Microsoft.Quantum.Simulators::0.23.195983", + "Microsoft.Quantum.Xunit::0.23.195983", + "Microsoft.Quantum.Standard::0.23.195983", + "Microsoft.Quantum.Standard.Visualization::0.23.195983", + "Microsoft.Quantum.Chemistry::0.23.195983", + "Microsoft.Quantum.Chemistry.Jupyter::0.23.195983", + "Microsoft.Quantum.MachineLearning::0.23.195983", + "Microsoft.Quantum.Numerics::0.23.195983", + "Microsoft.Quantum.Katas::0.23.195983", + "Microsoft.Quantum.Research::0.23.195983", + "Microsoft.Quantum.Providers.IonQ::0.23.195983", + "Microsoft.Quantum.Providers.Honeywell::0.23.195983", + "Microsoft.Quantum.Providers.QCI::0.23.195983", + "Microsoft.Quantum.Providers.Core::0.23.195983" ] } \ No newline at end of file From 1a49b0adca4589907dafdc5d69484010d14544fb Mon Sep 17 00:00:00 2001 From: Scott Carda Date: Thu, 3 Mar 2022 21:23:28 -0800 Subject: [PATCH 19/51] WIP for tests. --- src/AzureClient/Mocks/MockQIRSubmitter.cs | 68 +++++++++++++++++++++-- src/Tests/AzureClientEntryPointTests.cs | 30 ++++++++++ src/Tests/SNIPPETS.cs | 18 ++++++ 3 files changed, 112 insertions(+), 4 deletions(-) diff --git a/src/AzureClient/Mocks/MockQIRSubmitter.cs b/src/AzureClient/Mocks/MockQIRSubmitter.cs index 480319b016..468d7777e0 100644 --- a/src/AzureClient/Mocks/MockQIRSubmitter.cs +++ b/src/AzureClient/Mocks/MockQIRSubmitter.cs @@ -6,6 +6,7 @@ using System; using System.Reflection; using System.Threading; +using System.Linq; using System.Threading.Tasks; using Microsoft.Quantum.Runtime; using Microsoft.Quantum.Simulation.Core; @@ -19,11 +20,67 @@ internal class MockQIRSubmitter : IQirSubmitter { public string Target => throw new NotImplementedException(); - private IReadOnlyList Arguments = new List(); + private IReadOnlyList ExpectedArguments = new List(); - public MockQIRSubmitter(IReadOnlyList arguments) + public MockQIRSubmitter(IReadOnlyList expectedArguments) { - this.Arguments = arguments; + this.ExpectedArguments = expectedArguments; + } + + private bool IsArgumentValueEqual(ArgumentValue fst, ArgumentValue snd) + { + if (fst.Type != snd.Type) + { + return false; + } + + if (fst is ArgumentValue.Bool fstBool && snd is ArgumentValue.Bool sndBool) + { + return fstBool.Value == sndBool.Value; + } + else if (fst is ArgumentValue.Double fstDouble && snd is ArgumentValue.Double sndDouble) + { + return fstDouble.Value == sndDouble.Value; + } + else if (fst is ArgumentValue.Int fstInt && snd is ArgumentValue.Int sndInt) + { + return fstInt.Value == sndInt.Value; + } + else if (fst is ArgumentValue.String fstString && snd is ArgumentValue.String sndString) + { + return fstString.Value == sndString.Value; + } + else if (fst is ArgumentValue.Pauli fstPauli && snd is ArgumentValue.Pauli sndPauli) + { + return fstPauli.Value == sndPauli.Value; + } + else if (fst is ArgumentValue.Result fstResult && snd is ArgumentValue.Result sndResult) + { + return fstResult.Value == sndResult.Value; + } + + return false; + } + + private bool IsEqualToExpected(IReadOnlyList arguments) + { + if (this.ExpectedArguments.Count != arguments.Count) + { + return false; + } + + for (int i = 0; i < this.ExpectedArguments.Count; i++) + { + var expected = this.ExpectedArguments[i]; + var given = arguments[i]; + + if (expected.Name != given.Name || !IsArgumentValueEqual(expected.Value, given.Value)) + { + return false; + } + } + + return true; } public Task SubmitAsync(Stream qir, string entryPoint, IReadOnlyList arguments, SubmissionOptions options) @@ -31,7 +88,10 @@ public Task SubmitAsync(Stream qir, string entryPoint, IRead var job = new MockCloudJob(); MockAzureWorkspace.MockJobIds = new string[] { job.Id }; - + if (!IsEqualToExpected(arguments)) + { + throw new ArgumentException("The arguments passed to the SubmitAsync did not match the expected arguments to the Mock QIR submitter."); + } return Task.FromResult(job as IQuantumMachineJob); } diff --git a/src/Tests/AzureClientEntryPointTests.cs b/src/Tests/AzureClientEntryPointTests.cs index 17cfa3a289..2edecbba96 100644 --- a/src/Tests/AzureClientEntryPointTests.cs +++ b/src/Tests/AzureClientEntryPointTests.cs @@ -14,6 +14,7 @@ using Microsoft.Quantum.IQSharp.Jupyter; using Microsoft.Quantum.QsCompiler; using Microsoft.Quantum.QsCompiler.ReservedKeywords; +using Microsoft.Quantum.Runtime; using Microsoft.Quantum.Simulation.Common; using Microsoft.Quantum.Simulation.Core; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -81,6 +82,35 @@ public async Task FromSnippet() Assert.IsNotNull(job); } + [TestMethod] + public async Task ValidParameterTypes() + { + var entryPointGenerator = Init("Workspace", new string[] { SNIPPETS.ValidParameterTypes }); + var entryPoint = entryPointGenerator.Generate("ValidParameterTypes", null); + + Assert.IsNotNull(entryPoint); + + var validArguments = new List<(Argument, string)>() + { + (new Argument("myBool", new ArgumentValue.Bool(true)), "true"), + (new Argument("myDouble", new ArgumentValue.Double(1.2)), "1.2"), + (new Argument("myInt", new ArgumentValue.Int(2)), "2"), + (new Argument("myStr", new ArgumentValue.String("\"Hello\"")), "\"Hello\""), + (new Argument("myPauli", new ArgumentValue.Pauli(Pauli.PauliX)), "PauliX"), + (new Argument("myResult", new ArgumentValue.Result(Result.One)), "1"), + (new Argument("innerInt", new ArgumentValue.Int(7)), "7"), + (new Argument("innerDouble", new ArgumentValue.Double(6.4)), "6.4") + }; + + var job = await entryPoint.SubmitAsync( + new MockQIRSubmitter(validArguments.Select(x => x.Item1).ToList()), + new AzureSubmissionContext() + { + InputParameters = validArguments.ToDictionary(x => x.Item1.Name, x => x.Item2) + }); + Assert.IsNotNull(job); + } + [TestMethod] public void FromBrokenSnippet() { diff --git a/src/Tests/SNIPPETS.cs b/src/Tests/SNIPPETS.cs index 000d3d4cbd..df695e1318 100644 --- a/src/Tests/SNIPPETS.cs +++ b/src/Tests/SNIPPETS.cs @@ -365,5 +365,23 @@ operation ClassicalControl() : Result { } "; + public static string ValidParameterTypes = +@" + operation ValidParameterTypes( + myBool: Bool, + myDouble: Double, + myInt: Int, + myStr: String, + myPauli: Pauli, + myResult: Result, + (innerInt: Int, innerDouble: Double) + ) : Result { + use q = Qubit(); + H(q); + let r = M(q); + return r; + } +"; + } } From 8def9e1899443d41dc7deb1d2162c7488fb0b515 Mon Sep 17 00:00:00 2001 From: Scott Carda Date: Fri, 4 Mar 2022 14:43:48 -0800 Subject: [PATCH 20/51] update QDK version in AzureClient and fix unit test. --- src/AzureClient/AzureClient.csproj | 2 +- src/Tests/AzureClientEntryPointTests.cs | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/AzureClient/AzureClient.csproj b/src/AzureClient/AzureClient.csproj index 6aaa5956f9..6f258a7cb6 100644 --- a/src/AzureClient/AzureClient.csproj +++ b/src/AzureClient/AzureClient.csproj @@ -14,7 +14,7 @@ - + diff --git a/src/Tests/AzureClientEntryPointTests.cs b/src/Tests/AzureClientEntryPointTests.cs index 2edecbba96..105d6749ea 100644 --- a/src/Tests/AzureClientEntryPointTests.cs +++ b/src/Tests/AzureClientEntryPointTests.cs @@ -92,14 +92,14 @@ public async Task ValidParameterTypes() var validArguments = new List<(Argument, string)>() { - (new Argument("myBool", new ArgumentValue.Bool(true)), "true"), - (new Argument("myDouble", new ArgumentValue.Double(1.2)), "1.2"), - (new Argument("myInt", new ArgumentValue.Int(2)), "2"), + (new Argument("myBool", new ArgumentValue.Bool(true)), "\"true\""), + (new Argument("myDouble", new ArgumentValue.Double(1.2)), "\"1.2\""), + (new Argument("myInt", new ArgumentValue.Int(2)), "\"2\""), (new Argument("myStr", new ArgumentValue.String("\"Hello\"")), "\"Hello\""), - (new Argument("myPauli", new ArgumentValue.Pauli(Pauli.PauliX)), "PauliX"), - (new Argument("myResult", new ArgumentValue.Result(Result.One)), "1"), - (new Argument("innerInt", new ArgumentValue.Int(7)), "7"), - (new Argument("innerDouble", new ArgumentValue.Double(6.4)), "6.4") + (new Argument("myPauli", new ArgumentValue.Pauli(Pauli.PauliX)), "\"PauliX\""), + (new Argument("myResult", new ArgumentValue.Result(Result.One)), "\"1\""), + (new Argument("innerInt", new ArgumentValue.Int(7)), "\"7\""), + (new Argument("innerDouble", new ArgumentValue.Double(6.4)), "\"6.4\"") }; var job = await entryPoint.SubmitAsync( From fda57b2fe9765f444e637735345fc76e9436e0bc Mon Sep 17 00:00:00 2001 From: Scott Carda Date: Fri, 4 Mar 2022 15:37:12 -0800 Subject: [PATCH 21/51] more unit tests --- src/Tests/AzureClientEntryPointTests.cs | 46 +++++++++++++++++++++++++ src/Tests/SNIPPETS.cs | 24 +++++++++++++ 2 files changed, 70 insertions(+) diff --git a/src/Tests/AzureClientEntryPointTests.cs b/src/Tests/AzureClientEntryPointTests.cs index 105d6749ea..19ccdbe47c 100644 --- a/src/Tests/AzureClientEntryPointTests.cs +++ b/src/Tests/AzureClientEntryPointTests.cs @@ -82,6 +82,19 @@ public async Task FromSnippet() Assert.IsNotNull(job); } + [TestMethod] + public async Task QIRSubmission() + { + var entryPointGenerator = Init("Workspace", new string[] { SNIPPETS.HelloQ }); + var entryPoint = entryPointGenerator.Generate("HelloQ", null); + + Assert.IsNotNull(entryPoint); + var job = await entryPoint.SubmitAsync( + new MockQIRSubmitter(new List()), + new AzureSubmissionContext()); + Assert.IsNotNull(job); + } + [TestMethod] public async Task ValidParameterTypes() { @@ -111,6 +124,39 @@ public async Task ValidParameterTypes() Assert.IsNotNull(job); } + [TestMethod] + public async Task InvalidParameterTypes() + { + var entryPointGenerator = Init("Workspace", new string[] { SNIPPETS.InvalidParameterTypes }); + + var unitEntryPoint = entryPointGenerator.Generate("UnitType", null); + Assert.IsNotNull(unitEntryPoint); + await Assert.ThrowsExceptionAsync(() => unitEntryPoint.SubmitAsync( + new MockQIRSubmitter(new List()), + new AzureSubmissionContext() + { + InputParameters = new[] { ("myUnit", "\"()\"") }.ToDictionary(x => x.Item1, x => x.Item2) + })); + + var arrayEntryPoint = entryPointGenerator.Generate("ArrayType", null); + Assert.IsNotNull(arrayEntryPoint); + await Assert.ThrowsExceptionAsync(() => arrayEntryPoint.SubmitAsync( + new MockQIRSubmitter(new List()), + new AzureSubmissionContext() + { + InputParameters = new[] { ("myArray", "\"[2, 4, 8]\"") }.ToDictionary(x => x.Item1, x => x.Item2) + })); + + var rangeEntryPoint = entryPointGenerator.Generate("UnitType", null); + Assert.IsNotNull(rangeEntryPoint); + await Assert.ThrowsExceptionAsync(() => rangeEntryPoint.SubmitAsync( + new MockQIRSubmitter(new List()), + new AzureSubmissionContext() + { + InputParameters = new[] { ("myRange", "\"0..2..10\"") }.ToDictionary(x => x.Item1, x => x.Item2) + })); + } + [TestMethod] public void FromBrokenSnippet() { diff --git a/src/Tests/SNIPPETS.cs b/src/Tests/SNIPPETS.cs index df695e1318..33549ff53c 100644 --- a/src/Tests/SNIPPETS.cs +++ b/src/Tests/SNIPPETS.cs @@ -383,5 +383,29 @@ operation ValidParameterTypes( } "; + public static string InvalidParameterTypes = +@" + operation UnitType(myUnit: Unit) : Result { + use q = Qubit(); + H(q); + let r = M(q); + return r; + } + + operation ArrayType(myArray: Int[]) : Result { + use q = Qubit(); + H(q); + let r = M(q); + return r; + } + + operation RangeType(myRange: Range) : Result { + use q = Qubit(); + H(q); + let r = M(q); + return r; + } +"; + } } From 4b1fd03c98c0a0647f525ac7c14e8e014932fdc2 Mon Sep 17 00:00:00 2001 From: Scott Carda Date: Fri, 4 Mar 2022 15:42:40 -0800 Subject: [PATCH 22/51] updated unit test --- src/Tests/AzureClientEntryPointTests.cs | 15 ++++++++++++++- src/Tests/SNIPPETS.cs | 18 ++++++++++-------- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/src/Tests/AzureClientEntryPointTests.cs b/src/Tests/AzureClientEntryPointTests.cs index 19ccdbe47c..6b32b4fb29 100644 --- a/src/Tests/AzureClientEntryPointTests.cs +++ b/src/Tests/AzureClientEntryPointTests.cs @@ -147,7 +147,7 @@ await Assert.ThrowsExceptionAsync(() => arrayEntryPoint.Submi InputParameters = new[] { ("myArray", "\"[2, 4, 8]\"") }.ToDictionary(x => x.Item1, x => x.Item2) })); - var rangeEntryPoint = entryPointGenerator.Generate("UnitType", null); + var rangeEntryPoint = entryPointGenerator.Generate("RangeType", null); Assert.IsNotNull(rangeEntryPoint); await Assert.ThrowsExceptionAsync(() => rangeEntryPoint.SubmitAsync( new MockQIRSubmitter(new List()), @@ -155,6 +155,19 @@ await Assert.ThrowsExceptionAsync(() => rangeEntryPoint.Submi { InputParameters = new[] { ("myRange", "\"0..2..10\"") }.ToDictionary(x => x.Item1, x => x.Item2) })); + + var embeddedUnitEntryPoint = entryPointGenerator.Generate("EmbeddedUnitType", null); + Assert.IsNotNull(embeddedUnitEntryPoint); + await Assert.ThrowsExceptionAsync(() => embeddedUnitEntryPoint.SubmitAsync( + new MockQIRSubmitter(new List()), + new AzureSubmissionContext() + { + InputParameters = new[] { + ("myInt", "\"2\""), + ("myUnit", "\"()\""), + ("myBool", "\"true\"") + }.ToDictionary(x => x.Item1, x => x.Item2) + })); } [TestMethod] diff --git a/src/Tests/SNIPPETS.cs b/src/Tests/SNIPPETS.cs index 33549ff53c..e8e255ea2d 100644 --- a/src/Tests/SNIPPETS.cs +++ b/src/Tests/SNIPPETS.cs @@ -378,8 +378,7 @@ operation ValidParameterTypes( ) : Result { use q = Qubit(); H(q); - let r = M(q); - return r; + return M(q); } "; @@ -388,22 +387,25 @@ operation ValidParameterTypes( operation UnitType(myUnit: Unit) : Result { use q = Qubit(); H(q); - let r = M(q); - return r; + return M(q); } operation ArrayType(myArray: Int[]) : Result { use q = Qubit(); H(q); - let r = M(q); - return r; + return M(q); } operation RangeType(myRange: Range) : Result { use q = Qubit(); H(q); - let r = M(q); - return r; + return M(q); + } + + operation EmbeddedUnitType(myInt: Int, myUnit: Unit, myBool: Bool) : Result { + use q = Qubit(); + H(q); + return M(q); } "; From 4fde2e51615e676200b793a61a200039637116d8 Mon Sep 17 00:00:00 2001 From: Scott Carda Date: Fri, 4 Mar 2022 15:43:08 -0800 Subject: [PATCH 23/51] cleaned out comment --- src/AzureClient/AzureClient.cs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/AzureClient/AzureClient.cs b/src/AzureClient/AzureClient.cs index b94d1faa09..5d0aa86fb8 100644 --- a/src/AzureClient/AzureClient.cs +++ b/src/AzureClient/AzureClient.cs @@ -354,15 +354,6 @@ private async Task SubmitOrExecuteJobAsync( return AzureClientError.InvalidTarget.ToExecutionResult(); } - //var reader = new StreamReader(entryPoint.QirStream); - //channel?.Stdout(reader.ReadToEnd()); - //entryPoint.QirStream.Seek(0, SeekOrigin.Begin); - - //var job = await submitter.SubmitAsync( - // entryPoint.QirStream, - // $"ENTRYPOINT__{submissionContext.OperationName}", - // new List(), - // Runtime.Submitters.SubmissionOptions.Default.With(friendlyName: submissionContext.OperationName, shots: 1)); var job = await entryPoint.SubmitAsync(submitter, submissionContext); channel?.Stdout($"Job successfully submitted."); channel?.Stdout($" Job name: {submissionContext.FriendlyName}"); From f9f47d59718f96c064d1e02a022a62558c23f6fc Mon Sep 17 00:00:00 2001 From: Scott Carda Date: Fri, 4 Mar 2022 17:26:06 -0800 Subject: [PATCH 24/51] Removed unnecessary usings and updated copy write messages. --- src/AzureClient/AzureClient.cs | 1 - src/AzureClient/EntryPoint/IEntryPoint.cs | 3 --- src/AzureClient/Extensions.cs | 2 -- src/AzureClient/Mocks/MockQIRSubmitter.cs | 4 ---- src/Core/AssemblyInfo.cs | 2 +- src/Core/Compiler/CompilerMetadata.cs | 3 +-- src/Core/Compiler/CompilerService.cs | 3 +-- src/Core/Compiler/ICompilerService.cs | 2 +- src/Core/References/References.cs | 5 +---- src/Core/Workspace/Workspace.cs | 7 +------ src/Kernel/Magic/QirMagic.cs | 7 +------ src/Python/qsharp-core/qsharp/loader.py | 2 +- src/Tests/AzureClientTests.cs | 3 +-- src/Tests/SNIPPETS.cs | 6 +----- 14 files changed, 10 insertions(+), 40 deletions(-) diff --git a/src/AzureClient/AzureClient.cs b/src/AzureClient/AzureClient.cs index 5d0aa86fb8..a68320622d 100644 --- a/src/AzureClient/AzureClient.cs +++ b/src/AzureClient/AzureClient.cs @@ -6,7 +6,6 @@ using System; using System.Collections.Generic; using System.Diagnostics; -using System.IO; using System.Linq; using System.Net; using System.Threading; diff --git a/src/AzureClient/EntryPoint/IEntryPoint.cs b/src/AzureClient/EntryPoint/IEntryPoint.cs index 485163ad0d..b1de6100ca 100644 --- a/src/AzureClient/EntryPoint/IEntryPoint.cs +++ b/src/AzureClient/EntryPoint/IEntryPoint.cs @@ -3,10 +3,7 @@ #nullable enable -using System; -using System.Collections.Generic; using System.IO; -using System.Text; using System.Threading; using System.Threading.Tasks; using Microsoft.Quantum.Runtime; diff --git a/src/AzureClient/Extensions.cs b/src/AzureClient/Extensions.cs index 7950914828..bc5f7e3001 100644 --- a/src/AzureClient/Extensions.cs +++ b/src/AzureClient/Extensions.cs @@ -4,9 +4,7 @@ #nullable enable using System; -using System.Collections; using System.Collections.Generic; -using System.ComponentModel; using System.Threading.Tasks; using Microsoft.Azure.Quantum; using Microsoft.Extensions.DependencyInjection; diff --git a/src/AzureClient/Mocks/MockQIRSubmitter.cs b/src/AzureClient/Mocks/MockQIRSubmitter.cs index 468d7777e0..2222d55fb2 100644 --- a/src/AzureClient/Mocks/MockQIRSubmitter.cs +++ b/src/AzureClient/Mocks/MockQIRSubmitter.cs @@ -4,12 +4,8 @@ #nullable enable using System; -using System.Reflection; -using System.Threading; -using System.Linq; using System.Threading.Tasks; using Microsoft.Quantum.Runtime; -using Microsoft.Quantum.Simulation.Core; using Microsoft.Quantum.Runtime.Submitters; using System.IO; using System.Collections.Generic; diff --git a/src/Core/AssemblyInfo.cs b/src/Core/AssemblyInfo.cs index 44f1ffcf9d..686d7818bb 100644 --- a/src/Core/AssemblyInfo.cs +++ b/src/Core/AssemblyInfo.cs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. using System; diff --git a/src/Core/Compiler/CompilerMetadata.cs b/src/Core/Compiler/CompilerMetadata.cs index a518f77f90..e7440ac7ba 100644 --- a/src/Core/Compiler/CompilerMetadata.cs +++ b/src/Core/Compiler/CompilerMetadata.cs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. using System; @@ -9,7 +9,6 @@ using Microsoft.CodeAnalysis; using Microsoft.Quantum.QsCompiler.CompilationBuilder; -using Microsoft.Quantum.IQSharp.Common; using QsReferences = Microsoft.Quantum.QsCompiler.CompilationBuilder.References; diff --git a/src/Core/Compiler/CompilerService.cs b/src/Core/Compiler/CompilerService.cs index baab489807..a2067ca02e 100644 --- a/src/Core/Compiler/CompilerService.cs +++ b/src/Core/Compiler/CompilerService.cs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. #nullable enable @@ -27,7 +27,6 @@ using Microsoft.Quantum.QsCompiler.SyntaxTree; using Microsoft.Quantum.QsCompiler.Transformations.BasicTransformations; using Microsoft.Quantum.QsCompiler.Transformations.QsCodeOutput; -using Microsoft.Quantum.QsCompiler.Transformations.BasicTransformations; using Microsoft.Quantum.QsCompiler.Transformations.SyntaxTreeTrimming; using Microsoft.Quantum.QsCompiler.Transformations.Targeting; using QsReferences = Microsoft.Quantum.QsCompiler.CompilationBuilder.References; diff --git a/src/Core/Compiler/ICompilerService.cs b/src/Core/Compiler/ICompilerService.cs index 2dba509527..9ecad1b6bb 100644 --- a/src/Core/Compiler/ICompilerService.cs +++ b/src/Core/Compiler/ICompilerService.cs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. using System; diff --git a/src/Core/References/References.cs b/src/Core/References/References.cs index db7ffbcef7..2a70647cde 100644 --- a/src/Core/References/References.cs +++ b/src/Core/References/References.cs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. #nullable enable @@ -7,15 +7,12 @@ using System.Collections.Immutable; using System.Diagnostics; using System.Linq; -using System.Linq.Expressions; using System.Reflection; using System.Runtime.Loader; using System.Text.RegularExpressions; using System.Threading.Tasks; -using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; -using NuGet.Packaging.Core; namespace Microsoft.Quantum.IQSharp { diff --git a/src/Core/Workspace/Workspace.cs b/src/Core/Workspace/Workspace.cs index 380bcfcf82..aeba5291ce 100644 --- a/src/Core/Workspace/Workspace.cs +++ b/src/Core/Workspace/Workspace.cs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. using System; @@ -8,16 +8,11 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -using System.Xml.Linq; -using System.Xml.XPath; using Microsoft.CodeAnalysis; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Microsoft.Quantum.IQSharp.Common; -using NuGet.Frameworks; using NuGet.Packaging; -using NuGet.Packaging.Core; -using NuGet.Versioning; namespace Microsoft.Quantum.IQSharp { diff --git a/src/Kernel/Magic/QirMagic.cs b/src/Kernel/Magic/QirMagic.cs index 8fe9291eda..74e3e3f3d4 100644 --- a/src/Kernel/Magic/QirMagic.cs +++ b/src/Kernel/Magic/QirMagic.cs @@ -1,8 +1,6 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -using System; -using System.Diagnostics; using System.IO; using System.Threading.Tasks; using Microsoft.Extensions.Logging; @@ -10,10 +8,7 @@ using Microsoft.Quantum.IQSharp.AzureClient; using Microsoft.Quantum.IQSharp.Common; using Microsoft.Quantum.IQSharp.Jupyter; -using Microsoft.Quantum.IQSharp.Kernel; using Microsoft.Quantum.QsCompiler; -using Microsoft.Quantum.Simulation.Core; -using Microsoft.Quantum.Simulation.Simulators; namespace Microsoft.Quantum.IQSharp.Kernel { diff --git a/src/Python/qsharp-core/qsharp/loader.py b/src/Python/qsharp-core/qsharp/loader.py index a672c7dcc2..d25f96f55e 100644 --- a/src/Python/qsharp-core/qsharp/loader.py +++ b/src/Python/qsharp-core/qsharp/loader.py @@ -3,7 +3,7 @@ ## # loader.py: Support for exposing Q# namespaces as Python modules. ## -# Copyright (c) Microsoft Corporation. All rights reserved. +# Copyright (c) Microsoft Corporation. # Licensed under the MIT License. ## diff --git a/src/Tests/AzureClientTests.cs b/src/Tests/AzureClientTests.cs index ca483d5b5a..fdc9b0a19d 100644 --- a/src/Tests/AzureClientTests.cs +++ b/src/Tests/AzureClientTests.cs @@ -1,11 +1,10 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. #nullable enable using System; using System.Collections.Generic; -using System.Globalization; using System.Linq; using System.Threading; using System.Threading.Tasks; diff --git a/src/Tests/SNIPPETS.cs b/src/Tests/SNIPPETS.cs index e8e255ea2d..1d7dbc43e3 100644 --- a/src/Tests/SNIPPETS.cs +++ b/src/Tests/SNIPPETS.cs @@ -1,10 +1,6 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -using System; -using System.Collections.Generic; -using System.Text; - namespace Tests.IQSharp { public static class SNIPPETS From e3f7601e5315641f68a1552afc5fab310664e4d4 Mon Sep 17 00:00:00 2001 From: Scott Carda Date: Mon, 7 Mar 2022 12:49:39 -0800 Subject: [PATCH 25/51] Added some documentation. --- src/AzureClient/EntryPoint/EntryPoint.cs | 5 ++++- src/AzureClient/EntryPoint/EntryPointGenerator.cs | 1 + src/AzureClient/EntryPoint/IEntryPoint.cs | 12 +++++++++++- src/AzureClient/EntryPoint/IEntryPointGenerator.cs | 1 + src/Core/AssemblyInfo.cs | 3 +++ 5 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/AzureClient/EntryPoint/EntryPoint.cs b/src/AzureClient/EntryPoint/EntryPoint.cs index 726c4f1ec3..5e86db5acf 100644 --- a/src/AzureClient/EntryPoint/EntryPoint.cs +++ b/src/AzureClient/EntryPoint/EntryPoint.cs @@ -25,6 +25,8 @@ internal class EntryPoint : IEntryPoint private Type OutputType { get; } private OperationInfo OperationInfo { get; } private ILogger? Logger { get; } + + /// public Stream QirStream { get; } /// @@ -177,7 +179,8 @@ public Task SubmitAsync(IQuantumMachine machine, AzureSubmis return (Task)submitMethod.Invoke(machine, submitParameters); } - public Task SubmitAsync(IQirSubmitter submitter, AzureSubmissionContext submissionContext) + /// + public Task SubmitAsync(IQirSubmitter submitter, AzureSubmissionContext submissionContext, CancellationToken cancellationToken = default) { var entryPointInput = GetEntryPointInputArguments(submissionContext); diff --git a/src/AzureClient/EntryPoint/EntryPointGenerator.cs b/src/AzureClient/EntryPoint/EntryPointGenerator.cs index caa6529184..881591814b 100644 --- a/src/AzureClient/EntryPoint/EntryPointGenerator.cs +++ b/src/AzureClient/EntryPoint/EntryPointGenerator.cs @@ -79,6 +79,7 @@ public EntryPointGenerator( return null; } + /// public IEntryPoint Generate(string operationName, string? executionTarget, RuntimeCapability? runtimeCapability = null, bool forceQir = false) { diff --git a/src/AzureClient/EntryPoint/IEntryPoint.cs b/src/AzureClient/EntryPoint/IEntryPoint.cs index b1de6100ca..389c26b439 100644 --- a/src/AzureClient/EntryPoint/IEntryPoint.cs +++ b/src/AzureClient/EntryPoint/IEntryPoint.cs @@ -26,8 +26,18 @@ public interface IEntryPoint /// The details of the submitted job. public Task SubmitAsync(IQuantumMachine machine, AzureSubmissionContext submissionContext, CancellationToken cancellationToken = default); - public Task SubmitAsync(IQirSubmitter submitter, AzureSubmissionContext submissionContext); + /// + /// Submits the entry point for execution to Azure Quantum. + /// + /// The object representing the job submission target. + /// The object representing the submission context for the job. + /// /// Cancellation token used to interrupt this submission. + /// The details of the submitted job. + public Task SubmitAsync(IQirSubmitter submitter, AzureSubmissionContext submissionContext, CancellationToken cancellationToken = default); + /// + /// The stream from which QIR bitcode for the entry point can be read. + /// public Stream QirStream { get; } } } diff --git a/src/AzureClient/EntryPoint/IEntryPointGenerator.cs b/src/AzureClient/EntryPoint/IEntryPointGenerator.cs index 6249abb5d4..1735fd7450 100644 --- a/src/AzureClient/EntryPoint/IEntryPointGenerator.cs +++ b/src/AzureClient/EntryPoint/IEntryPointGenerator.cs @@ -40,6 +40,7 @@ public interface IEntryPointGenerator /// The name of the operation to wrap in an entry point. /// The intended execution target for the compiled entry point. /// The runtime capabilities of the intended execution target. + /// When true, uses QIR to generate the entry point. /// The generated entry point. public IEntryPoint Generate(string operationName, string? executionTarget, RuntimeCapability? runtimeCapabilities = null, bool forceQir = false); diff --git a/src/Core/AssemblyInfo.cs b/src/Core/AssemblyInfo.cs index 686d7818bb..be767e75b0 100644 --- a/src/Core/AssemblyInfo.cs +++ b/src/Core/AssemblyInfo.cs @@ -73,6 +73,9 @@ public AssemblyInfo(Assembly assembly, string location, QsNamespace[] syntaxTree /// public QsNamespace[] SyntaxTree { get; } + /// + /// The stream from which QIR bitcode for the entry point can be read. + /// public Stream QirBitcode { get; } /// From 4d164a5b2e66c3751b6476e663bd7702b06de015 Mon Sep 17 00:00:00 2001 From: Scott Carda Date: Mon, 7 Mar 2022 12:54:21 -0800 Subject: [PATCH 26/51] updated todo --- src/Tests/AzureClientTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Tests/AzureClientTests.cs b/src/Tests/AzureClientTests.cs index fdc9b0a19d..1b101e96b1 100644 --- a/src/Tests/AzureClientTests.cs +++ b/src/Tests/AzureClientTests.cs @@ -180,7 +180,7 @@ public void TestAllTargets() var targets = ExpectSuccess>(ConnectToWorkspaceAsync(azureClient, MockAzureWorkspace.NameWithMockProviders)); // 2 targets per provider: mock and simulator. - // TODO: UNCOMMENT + // TODO: uncomment once there is a microsoft.mock target //Assert.AreEqual(2 * Enum.GetNames(typeof(AzureProvider)).Length, targets.Count()); // set each target, which will load the corresponding package From aec5f36dfff9f3de23378460cc98ad4d3054831d Mon Sep 17 00:00:00 2001 From: Scott Carda Date: Tue, 8 Mar 2022 10:39:34 -0800 Subject: [PATCH 27/51] Link to issue. --- src/AzureClient/Visualization/HistogramEncoders.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/AzureClient/Visualization/HistogramEncoders.cs b/src/AzureClient/Visualization/HistogramEncoders.cs index dabe2717e8..d3b96f08fe 100644 --- a/src/AzureClient/Visualization/HistogramEncoders.cs +++ b/src/AzureClient/Visualization/HistogramEncoders.cs @@ -30,6 +30,7 @@ internal static Histogram ToHistogram(this Stream stream, ILogger? logger = null output = "{ \"Histogram\" : [ \"" + output.Trim() + "\", 1.0 ] }"; // TODO: Make this more general. The corresponding implementation from the az quantum cli is: + // https://github.com/microsoft/iqsharp/issues/607 // // if job.target.startswith("microsoft.simulator"): // From 5c84a0904799378fe9e71f60490355aaea700510 Mon Sep 17 00:00:00 2001 From: Scott Carda Date: Tue, 8 Mar 2022 11:28:22 -0800 Subject: [PATCH 28/51] some PR suggestions --- src/AzureClient/EntryPoint/EntryPoint.cs | 2 +- .../EntryPoint/IEntryPointGenerator.cs | 2 +- src/AzureClient/Mocks/MockQIRSubmitter.cs | 66 ++++++------------- src/Tests/AzureClientEntryPointTests.cs | 32 ++++----- src/Tests/SNIPPETS.cs | 10 +-- 5 files changed, 44 insertions(+), 68 deletions(-) diff --git a/src/AzureClient/EntryPoint/EntryPoint.cs b/src/AzureClient/EntryPoint/EntryPoint.cs index 5e86db5acf..8a6add9589 100644 --- a/src/AzureClient/EntryPoint/EntryPoint.cs +++ b/src/AzureClient/EntryPoint/EntryPoint.cs @@ -64,7 +64,7 @@ private object GetEntryPointInputObject(AzureSubmissionContext submissionContext throw new ArgumentException($"Required parameter {parameter.Name} was not specified."); } - string rawParameterValue = submissionContext.InputParameters[parameter.Name]; + var rawParameterValue = submissionContext.InputParameters[parameter.Name]; try { var parameterValue = submissionContext.InputParameters.DecodeParameter(parameter.Name, type: parameter.ParameterType); diff --git a/src/AzureClient/EntryPoint/IEntryPointGenerator.cs b/src/AzureClient/EntryPoint/IEntryPointGenerator.cs index 1735fd7450..ec70adf520 100644 --- a/src/AzureClient/EntryPoint/IEntryPointGenerator.cs +++ b/src/AzureClient/EntryPoint/IEntryPointGenerator.cs @@ -40,7 +40,7 @@ public interface IEntryPointGenerator /// The name of the operation to wrap in an entry point. /// The intended execution target for the compiled entry point. /// The runtime capabilities of the intended execution target. - /// When true, uses QIR to generate the entry point. + /// When true, uses QIR to generate the entry point. /// The generated entry point. public IEntryPoint Generate(string operationName, string? executionTarget, RuntimeCapability? runtimeCapabilities = null, bool forceQir = false); diff --git a/src/AzureClient/Mocks/MockQIRSubmitter.cs b/src/AzureClient/Mocks/MockQIRSubmitter.cs index 2222d55fb2..adf54bc5ca 100644 --- a/src/AzureClient/Mocks/MockQIRSubmitter.cs +++ b/src/AzureClient/Mocks/MockQIRSubmitter.cs @@ -9,6 +9,7 @@ using Microsoft.Quantum.Runtime.Submitters; using System.IO; using System.Collections.Generic; +using System.Linq; namespace Microsoft.Quantum.IQSharp.AzureClient { @@ -23,40 +24,24 @@ public MockQIRSubmitter(IReadOnlyList expectedArguments) this.ExpectedArguments = expectedArguments; } - private bool IsArgumentValueEqual(ArgumentValue fst, ArgumentValue snd) - { - if (fst.Type != snd.Type) - { - return false; - } - - if (fst is ArgumentValue.Bool fstBool && snd is ArgumentValue.Bool sndBool) - { - return fstBool.Value == sndBool.Value; - } - else if (fst is ArgumentValue.Double fstDouble && snd is ArgumentValue.Double sndDouble) - { - return fstDouble.Value == sndDouble.Value; - } - else if (fst is ArgumentValue.Int fstInt && snd is ArgumentValue.Int sndInt) - { - return fstInt.Value == sndInt.Value; - } - else if (fst is ArgumentValue.String fstString && snd is ArgumentValue.String sndString) + private bool IsArgumentValueEqual(ArgumentValue fst, ArgumentValue snd) => + (fst, snd) switch { - return fstString.Value == sndString.Value; - } - else if (fst is ArgumentValue.Pauli fstPauli && snd is ArgumentValue.Pauli sndPauli) - { - return fstPauli.Value == sndPauli.Value; - } - else if (fst is ArgumentValue.Result fstResult && snd is ArgumentValue.Result sndResult) - { - return fstResult.Value == sndResult.Value; - } - - return false; - } + (_, _) when (fst.Type != snd.Type) => false, + (ArgumentValue.Bool { Value: var fstVal }, ArgumentValue.Bool { Value: var sndVal }) => + fstVal == sndVal, + (ArgumentValue.Double { Value: var fstVal }, ArgumentValue.Double { Value: var sndVal }) => + fstVal == sndVal, + (ArgumentValue.Int { Value: var fstVal }, ArgumentValue.Int { Value: var sndVal }) => + fstVal == sndVal, + (ArgumentValue.String { Value: var fstVal }, ArgumentValue.String { Value: var sndVal }) => + fstVal == sndVal, + (ArgumentValue.Pauli { Value: var fstVal }, ArgumentValue.Pauli { Value: var sndVal }) => + fstVal == sndVal, + (ArgumentValue.Result { Value: var fstVal }, ArgumentValue.Result { Value: var sndVal }) => + fstVal == sndVal, + _ => false + }; private bool IsEqualToExpected(IReadOnlyList arguments) { @@ -65,18 +50,9 @@ private bool IsEqualToExpected(IReadOnlyList arguments) return false; } - for (int i = 0; i < this.ExpectedArguments.Count; i++) - { - var expected = this.ExpectedArguments[i]; - var given = arguments[i]; - - if (expected.Name != given.Name || !IsArgumentValueEqual(expected.Value, given.Value)) - { - return false; - } - } - - return true; + return this.ExpectedArguments + .Zip(arguments, (fst, snd) => (fst, snd)) + .All(tup => tup.fst.Name == tup.snd.Name && IsArgumentValueEqual(tup.fst.Value, tup.snd.Value)); } public Task SubmitAsync(Stream qir, string entryPoint, IReadOnlyList arguments, SubmissionOptions options) diff --git a/src/Tests/AzureClientEntryPointTests.cs b/src/Tests/AzureClientEntryPointTests.cs index 6b32b4fb29..c30d2e4f89 100644 --- a/src/Tests/AzureClientEntryPointTests.cs +++ b/src/Tests/AzureClientEntryPointTests.cs @@ -99,27 +99,27 @@ public async Task QIRSubmission() public async Task ValidParameterTypes() { var entryPointGenerator = Init("Workspace", new string[] { SNIPPETS.ValidParameterTypes }); - var entryPoint = entryPointGenerator.Generate("ValidParameterTypes", null); + var entryPoint = entryPointGenerator.Generate("UseValidParameterTypes", null); Assert.IsNotNull(entryPoint); - var validArguments = new List<(Argument, string)>() + var validArguments = new Dictionary() { - (new Argument("myBool", new ArgumentValue.Bool(true)), "\"true\""), - (new Argument("myDouble", new ArgumentValue.Double(1.2)), "\"1.2\""), - (new Argument("myInt", new ArgumentValue.Int(2)), "\"2\""), - (new Argument("myStr", new ArgumentValue.String("\"Hello\"")), "\"Hello\""), - (new Argument("myPauli", new ArgumentValue.Pauli(Pauli.PauliX)), "\"PauliX\""), - (new Argument("myResult", new ArgumentValue.Result(Result.One)), "\"1\""), - (new Argument("innerInt", new ArgumentValue.Int(7)), "\"7\""), - (new Argument("innerDouble", new ArgumentValue.Double(6.4)), "\"6.4\"") + { new Argument("myBool", new ArgumentValue.Bool(true)), "\"true\"" }, + { new Argument("myDouble", new ArgumentValue.Double(1.2)), "\"1.2\"" }, + { new Argument("myInt", new ArgumentValue.Int(2)), "\"2\"" }, + { new Argument("myStr", new ArgumentValue.String("\"Hello\"")), "\"Hello\"" }, + { new Argument("myPauli", new ArgumentValue.Pauli(Pauli.PauliX)), "\"PauliX\"" }, + { new Argument("myResult", new ArgumentValue.Result(Result.One)) , "\"1\"" }, + { new Argument("innerInt", new ArgumentValue.Int(7)) , "\"7\"" }, + { new Argument("innerDouble", new ArgumentValue.Double(6.4)) , "\"6.4\"" } }; var job = await entryPoint.SubmitAsync( - new MockQIRSubmitter(validArguments.Select(x => x.Item1).ToList()), + new MockQIRSubmitter(validArguments.Select(x => x.Key).ToList()), new AzureSubmissionContext() { - InputParameters = validArguments.ToDictionary(x => x.Item1.Name, x => x.Item2) + InputParameters = validArguments.ToDictionary(x => x.Key.Name, x => x.Value) }); Assert.IsNotNull(job); } @@ -129,7 +129,7 @@ public async Task InvalidParameterTypes() { var entryPointGenerator = Init("Workspace", new string[] { SNIPPETS.InvalidParameterTypes }); - var unitEntryPoint = entryPointGenerator.Generate("UnitType", null); + var unitEntryPoint = entryPointGenerator.Generate("UseUnitType", null); Assert.IsNotNull(unitEntryPoint); await Assert.ThrowsExceptionAsync(() => unitEntryPoint.SubmitAsync( new MockQIRSubmitter(new List()), @@ -138,7 +138,7 @@ await Assert.ThrowsExceptionAsync(() => unitEntryPoint.Submit InputParameters = new[] { ("myUnit", "\"()\"") }.ToDictionary(x => x.Item1, x => x.Item2) })); - var arrayEntryPoint = entryPointGenerator.Generate("ArrayType", null); + var arrayEntryPoint = entryPointGenerator.Generate("UseArrayType", null); Assert.IsNotNull(arrayEntryPoint); await Assert.ThrowsExceptionAsync(() => arrayEntryPoint.SubmitAsync( new MockQIRSubmitter(new List()), @@ -147,7 +147,7 @@ await Assert.ThrowsExceptionAsync(() => arrayEntryPoint.Submi InputParameters = new[] { ("myArray", "\"[2, 4, 8]\"") }.ToDictionary(x => x.Item1, x => x.Item2) })); - var rangeEntryPoint = entryPointGenerator.Generate("RangeType", null); + var rangeEntryPoint = entryPointGenerator.Generate("UseRangeType", null); Assert.IsNotNull(rangeEntryPoint); await Assert.ThrowsExceptionAsync(() => rangeEntryPoint.SubmitAsync( new MockQIRSubmitter(new List()), @@ -156,7 +156,7 @@ await Assert.ThrowsExceptionAsync(() => rangeEntryPoint.Submi InputParameters = new[] { ("myRange", "\"0..2..10\"") }.ToDictionary(x => x.Item1, x => x.Item2) })); - var embeddedUnitEntryPoint = entryPointGenerator.Generate("EmbeddedUnitType", null); + var embeddedUnitEntryPoint = entryPointGenerator.Generate("UseEmbeddedUnitType", null); Assert.IsNotNull(embeddedUnitEntryPoint); await Assert.ThrowsExceptionAsync(() => embeddedUnitEntryPoint.SubmitAsync( new MockQIRSubmitter(new List()), diff --git a/src/Tests/SNIPPETS.cs b/src/Tests/SNIPPETS.cs index 1d7dbc43e3..aac8d6b48b 100644 --- a/src/Tests/SNIPPETS.cs +++ b/src/Tests/SNIPPETS.cs @@ -363,7 +363,7 @@ operation ClassicalControl() : Result { public static string ValidParameterTypes = @" - operation ValidParameterTypes( + operation UseValidParameterTypes( myBool: Bool, myDouble: Double, myInt: Int, @@ -380,25 +380,25 @@ operation ValidParameterTypes( public static string InvalidParameterTypes = @" - operation UnitType(myUnit: Unit) : Result { + operation UseUnitType(myUnit: Unit) : Result { use q = Qubit(); H(q); return M(q); } - operation ArrayType(myArray: Int[]) : Result { + operation UseArrayType(myArray: Int[]) : Result { use q = Qubit(); H(q); return M(q); } - operation RangeType(myRange: Range) : Result { + operation UseRangeType(myRange: Range) : Result { use q = Qubit(); H(q); return M(q); } - operation EmbeddedUnitType(myInt: Int, myUnit: Unit, myBool: Bool) : Result { + operation UseEmbeddedUnitType(myInt: Int, myUnit: Unit, myBool: Bool) : Result { use q = Qubit(); H(q); return M(q); From 78ecc32e904db972078416b0589e31cddd4467d4 Mon Sep 17 00:00:00 2001 From: Scott Carda Date: Tue, 8 Mar 2022 12:15:45 -0800 Subject: [PATCH 29/51] nullable QIR Stream in Entry Point --- src/AzureClient/EntryPoint/EntryPoint.cs | 4 ++-- src/AzureClient/EntryPoint/IEntryPoint.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/AzureClient/EntryPoint/EntryPoint.cs b/src/AzureClient/EntryPoint/EntryPoint.cs index 8a6add9589..ceb674898a 100644 --- a/src/AzureClient/EntryPoint/EntryPoint.cs +++ b/src/AzureClient/EntryPoint/EntryPoint.cs @@ -27,7 +27,7 @@ internal class EntryPoint : IEntryPoint private ILogger? Logger { get; } /// - public Stream QirStream { get; } + public Stream? QirStream { get; } /// /// Creates an object used to submit jobs to Azure Quantum. @@ -43,7 +43,7 @@ internal class EntryPoint : IEntryPoint /// Stream from which QIR bitcode for the entry point can be read. /// /// Logger used to report internal diagnostics. - public EntryPoint(object entryPointInfo, Type inputType, Type outputType, OperationInfo operationInfo, Stream qirStream, ILogger? logger) + public EntryPoint(object entryPointInfo, Type inputType, Type outputType, OperationInfo operationInfo, Stream? qirStream, ILogger? logger) { EntryPointInfo = entryPointInfo; InputType = inputType; diff --git a/src/AzureClient/EntryPoint/IEntryPoint.cs b/src/AzureClient/EntryPoint/IEntryPoint.cs index 389c26b439..591ce4d739 100644 --- a/src/AzureClient/EntryPoint/IEntryPoint.cs +++ b/src/AzureClient/EntryPoint/IEntryPoint.cs @@ -38,6 +38,6 @@ public interface IEntryPoint /// /// The stream from which QIR bitcode for the entry point can be read. /// - public Stream QirStream { get; } + public Stream? QirStream { get; } } } From 889ee1ba729fcd6a5af7ad9d04f9f8ced8842b18 Mon Sep 17 00:00:00 2001 From: Scott Carda Date: Tue, 8 Mar 2022 12:48:39 -0800 Subject: [PATCH 30/51] more PR suggestions --- src/AzureClient/AzureClient.cs | 6 +++--- src/AzureClient/EntryPoint/EntryPoint.cs | 7 ++++++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/AzureClient/AzureClient.cs b/src/AzureClient/AzureClient.cs index a68320622d..6a6187b49b 100644 --- a/src/AzureClient/AzureClient.cs +++ b/src/AzureClient/AzureClient.cs @@ -42,9 +42,9 @@ public class AzureClient : IAzureClient private string MostRecentJobId { get; set; } = string.Empty; private IEnumerable? AvailableProviders { get; set; } private IEnumerable? AvailableTargets => - AvailableProviders? - .SelectMany(provider => provider.Targets) - .Where(t => t.TargetId != null && (t.TargetId.StartsWith(MicrosoftSimulator) || AzureExecutionTarget.GetProvider(t.TargetId) != AzureProvider.Microsoft)); + AvailableProviders + ?.SelectMany(provider => provider.Targets) + ?.Where(t => t.TargetId != null && (t.TargetId.StartsWith(MicrosoftSimulator) || AzureExecutionTarget.GetProvider(t.TargetId) != AzureProvider.Microsoft)); private IEnumerable? ValidExecutionTargets => AvailableTargets?.Where(AzureExecutionTarget.IsValid); private string ValidExecutionTargetsDisplayText => (ValidExecutionTargets == null || ValidExecutionTargets.Count() == 0) diff --git a/src/AzureClient/EntryPoint/EntryPoint.cs b/src/AzureClient/EntryPoint/EntryPoint.cs index ceb674898a..470867cd3e 100644 --- a/src/AzureClient/EntryPoint/EntryPoint.cs +++ b/src/AzureClient/EntryPoint/EntryPoint.cs @@ -115,7 +115,7 @@ private ArgumentValue GetArgumentValue(string parameterValue, System.Reflection. } else if (parameterType == typeof(Result)) { - return new ArgumentValue.Result(Newtonsoft.Json.JsonConvert.DeserializeObject(parameterValue)); + return new ArgumentValue.Result(Newtonsoft.Json.JsonConvert.DeserializeObject(parameterValue)!); } else { @@ -182,6 +182,11 @@ public Task SubmitAsync(IQuantumMachine machine, AzureSubmis /// public Task SubmitAsync(IQirSubmitter submitter, AzureSubmissionContext submissionContext, CancellationToken cancellationToken = default) { + if ( QirStream is null ) + { + throw new ArgumentException("A QIR stream is required for submission using a QIR submitter. No QIR stream was found."); + } + var entryPointInput = GetEntryPointInputArguments(submissionContext); var options = SubmissionOptions.Default; From 9e0f3f474d3390ab3facce304c592dc8b34254f7 Mon Sep 17 00:00:00 2001 From: Scott Carda Date: Tue, 8 Mar 2022 15:02:34 -0800 Subject: [PATCH 31/51] Added error handling to the microsoft.simulator case. --- src/AzureClient/AzureClient.cs | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/src/AzureClient/AzureClient.cs b/src/AzureClient/AzureClient.cs index 6a6187b49b..96975f46f9 100644 --- a/src/AzureClient/AzureClient.cs +++ b/src/AzureClient/AzureClient.cs @@ -353,11 +353,34 @@ private async Task SubmitOrExecuteJobAsync( return AzureClientError.InvalidTarget.ToExecutionResult(); } - var job = await entryPoint.SubmitAsync(submitter, submissionContext); - channel?.Stdout($"Job successfully submitted."); - channel?.Stdout($" Job name: {submissionContext.FriendlyName}"); - channel?.Stdout($" Job ID: {job.Id}"); - MostRecentJobId = job.Id; + try + { + Logger.LogDebug("About to submit entry point for {OperationName}.", submissionContext.OperationName); + var job = await entryPoint.SubmitAsync(submitter, submissionContext); + channel?.Stdout($"Job successfully submitted."); + channel?.Stdout($" Job name: {submissionContext.FriendlyName}"); + channel?.Stdout($" Job ID: {job.Id}"); + MostRecentJobId = job.Id; + } + catch (TaskCanceledException tce) + { + throw tce; + } + catch (ArgumentException e) + { + var msg = $"Failed to parse all expected parameters for Q# operation {submissionContext.OperationName}."; + Logger.LogError(e, msg); + + channel?.Stderr(msg); + channel?.Stderr(e.Message); + return AzureClientError.JobSubmissionFailed.ToExecutionResult(); + } + catch (Exception e) + { + channel?.Stderr($"Failed to submit Q# operation {submissionContext.OperationName} for execution."); + channel?.Stderr(e.InnerException?.Message ?? e.Message); + return AzureClientError.JobSubmissionFailed.ToExecutionResult(); + } } else { From 16a89ccff645fb8927491f969a2d9527f41ace19 Mon Sep 17 00:00:00 2001 From: Cassandra Granade Date: Wed, 9 Mar 2022 00:45:17 +0000 Subject: [PATCH 32/51] Deduplicate error handling in AzureClient.cs. --- src/AzureClient/AzureClient.cs | 114 +++++++++++++-------------------- 1 file changed, 46 insertions(+), 68 deletions(-) diff --git a/src/AzureClient/AzureClient.cs b/src/AzureClient/AzureClient.cs index 96975f46f9..ce0cf434f0 100644 --- a/src/AzureClient/AzureClient.cs +++ b/src/AzureClient/AzureClient.cs @@ -343,83 +343,61 @@ private async Task SubmitOrExecuteJobAsync( channel?.Stdout($"Submitting {submissionContext.OperationName} to target {ActiveTarget.TargetId}..."); - if (this.ActiveTarget.TargetId.StartsWith(MicrosoftSimulator)) + try { - var submitter = SubmitterFactory.QirSubmitter(this.ActiveTarget.TargetId, this.ActiveWorkspace, this.StorageConnectionString); - if (submitter == null) - { - // We should never get here, since ActiveTarget should have already been validated at the time it was set. - channel?.Stderr($"Unexpected error while preparing job for execution on target {ActiveTarget.TargetId}."); - return AzureClientError.InvalidTarget.ToExecutionResult(); - } - - try + // QirSubmitter and CreateMachine have return types with different base types + // but both have a SubmitAsync method that returns an IQuantumMachineJob. + // Thus, we can branch on whether we need a QIR submitter or a translator, + // but can use the same task object to represent both return values. + Task? jobTask = null; + if (this.ActiveTarget.TargetId.StartsWith(MicrosoftSimulator)) { - Logger.LogDebug("About to submit entry point for {OperationName}.", submissionContext.OperationName); - var job = await entryPoint.SubmitAsync(submitter, submissionContext); - channel?.Stdout($"Job successfully submitted."); - channel?.Stdout($" Job name: {submissionContext.FriendlyName}"); - channel?.Stdout($" Job ID: {job.Id}"); - MostRecentJobId = job.Id; + var submitter = SubmitterFactory.QirSubmitter(this.ActiveTarget.TargetId, this.ActiveWorkspace, this.StorageConnectionString); + if (submitter == null) + { + // We should never get here, since ActiveTarget should have already been validated at the time it was set. + channel?.Stderr($"Unexpected error while preparing job for execution on target {ActiveTarget.TargetId}."); + return AzureClientError.InvalidTarget.ToExecutionResult(); + } + jobTask = entryPoint.SubmitAsync(submitter, submissionContext); } - catch (TaskCanceledException tce) + else { - throw tce; + var machine = AzureFactory.CreateMachine(this.ActiveWorkspace, this.ActiveTarget.TargetId, this.StorageConnectionString); + if (machine == null) + { + // We should never get here, since ActiveTarget should have already been validated at the time it was set. + channel?.Stderr($"Unexpected error while preparing job for execution on target {ActiveTarget.TargetId}."); + return AzureClientError.InvalidTarget.ToExecutionResult(); + } + jobTask = entryPoint.SubmitAsync(machine, submissionContext); } - catch (ArgumentException e) - { - var msg = $"Failed to parse all expected parameters for Q# operation {submissionContext.OperationName}."; - Logger.LogError(e, msg); - channel?.Stderr(msg); - channel?.Stderr(e.Message); - return AzureClientError.JobSubmissionFailed.ToExecutionResult(); - } - catch (Exception e) - { - channel?.Stderr($"Failed to submit Q# operation {submissionContext.OperationName} for execution."); - channel?.Stderr(e.InnerException?.Message ?? e.Message); - return AzureClientError.JobSubmissionFailed.ToExecutionResult(); - } + Logger.LogDebug("About to submit entry point for {OperationName}.", submissionContext.OperationName); + var job = await jobTask; + channel?.Stdout($"Job successfully submitted."); + channel?.Stdout($" Job name: {submissionContext.FriendlyName}"); + channel?.Stdout($" Job ID: {job.Id}"); + MostRecentJobId = job.Id; } - else + catch (TaskCanceledException tce) { - var machine = AzureFactory.CreateMachine(this.ActiveWorkspace, this.ActiveTarget.TargetId, this.StorageConnectionString); - if (machine == null) - { - // We should never get here, since ActiveTarget should have already been validated at the time it was set. - channel?.Stderr($"Unexpected error while preparing job for execution on target {ActiveTarget.TargetId}."); - return AzureClientError.InvalidTarget.ToExecutionResult(); - } - - try - { - Logger.LogDebug("About to submit entry point for {OperationName}.", submissionContext.OperationName); - var job = await entryPoint.SubmitAsync(machine, submissionContext); - channel?.Stdout($"Job successfully submitted for {submissionContext.Shots} shots."); - channel?.Stdout($" Job name: {submissionContext.FriendlyName}"); - channel?.Stdout($" Job ID: {job.Id}"); - MostRecentJobId = job.Id; - } - catch (TaskCanceledException tce) - { - throw tce; - } - catch (ArgumentException e) - { - var msg = $"Failed to parse all expected parameters for Q# operation {submissionContext.OperationName}."; - Logger.LogError(e, msg); + throw tce; + } + catch (ArgumentException e) + { + var msg = $"Failed to parse all expected parameters for Q# operation {submissionContext.OperationName}."; + Logger.LogError(e, msg); - channel?.Stderr(msg); - channel?.Stderr(e.Message); - return AzureClientError.JobSubmissionFailed.ToExecutionResult(); - } - catch (Exception e) - { - channel?.Stderr($"Failed to submit Q# operation {submissionContext.OperationName} for execution."); - channel?.Stderr(e.InnerException?.Message ?? e.Message); - return AzureClientError.JobSubmissionFailed.ToExecutionResult(); - } + channel?.Stderr(msg); + channel?.Stderr(e.Message); + return AzureClientError.JobSubmissionFailed.ToExecutionResult(); + } + catch (Exception e) + { + channel?.Stderr($"Failed to submit Q# operation {submissionContext.OperationName} for execution."); + channel?.Stderr(e.InnerException?.Message ?? e.Message); + return AzureClientError.JobSubmissionFailed.ToExecutionResult(); } // If the command was not %azure.execute, simply return the job status. From 85f03789735dc178b8cc0e861866cbfaa494c232 Mon Sep 17 00:00:00 2001 From: Scott Carda Date: Tue, 8 Mar 2022 21:20:52 -0800 Subject: [PATCH 33/51] fixed tests --- src/AzureClient/EntryPoint/EntryPoint.cs | 7 +------ src/Tests/AzureClientEntryPointTests.cs | 4 ++-- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/src/AzureClient/EntryPoint/EntryPoint.cs b/src/AzureClient/EntryPoint/EntryPoint.cs index 470867cd3e..52403e63fc 100644 --- a/src/AzureClient/EntryPoint/EntryPoint.cs +++ b/src/AzureClient/EntryPoint/EntryPoint.cs @@ -182,11 +182,6 @@ public Task SubmitAsync(IQuantumMachine machine, AzureSubmis /// public Task SubmitAsync(IQirSubmitter submitter, AzureSubmissionContext submissionContext, CancellationToken cancellationToken = default) { - if ( QirStream is null ) - { - throw new ArgumentException("A QIR stream is required for submission using a QIR submitter. No QIR stream was found."); - } - var entryPointInput = GetEntryPointInputArguments(submissionContext); var options = SubmissionOptions.Default; @@ -204,7 +199,7 @@ public Task SubmitAsync(IQirSubmitter submitter, AzureSubmis && method.GetParameters()[2].ParameterType == typeof(IReadOnlyList) && method.GetParameters()[3].ParameterType == typeof(SubmissionOptions) ); - var submitParameters = new object[] { QirStream, $"ENTRYPOINT__{submissionContext.OperationName}", entryPointInput, options }; + var submitParameters = new object[] { QirStream!, $"ENTRYPOINT__{submissionContext.OperationName}", entryPointInput, options }; return (Task)submitMethod.Invoke(submitter, submitParameters); } } diff --git a/src/Tests/AzureClientEntryPointTests.cs b/src/Tests/AzureClientEntryPointTests.cs index c30d2e4f89..5b96a5b262 100644 --- a/src/Tests/AzureClientEntryPointTests.cs +++ b/src/Tests/AzureClientEntryPointTests.cs @@ -86,7 +86,7 @@ public async Task FromSnippet() public async Task QIRSubmission() { var entryPointGenerator = Init("Workspace", new string[] { SNIPPETS.HelloQ }); - var entryPoint = entryPointGenerator.Generate("HelloQ", null); + var entryPoint = entryPointGenerator.Generate("HelloQ", null, forceQir: true); Assert.IsNotNull(entryPoint); var job = await entryPoint.SubmitAsync( @@ -99,7 +99,7 @@ public async Task QIRSubmission() public async Task ValidParameterTypes() { var entryPointGenerator = Init("Workspace", new string[] { SNIPPETS.ValidParameterTypes }); - var entryPoint = entryPointGenerator.Generate("UseValidParameterTypes", null); + var entryPoint = entryPointGenerator.Generate("UseValidParameterTypes", null, forceQir: true); Assert.IsNotNull(entryPoint); From de038fae8178fe5d2dfcffb51479a053a4a28b98 Mon Sep 17 00:00:00 2001 From: Scott Carda Date: Wed, 9 Mar 2022 12:13:42 -0800 Subject: [PATCH 34/51] updated as_qir in the loader.py --- src/Python/qsharp-core/qsharp/loader.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/Python/qsharp-core/qsharp/loader.py b/src/Python/qsharp-core/qsharp/loader.py index d25f96f55e..e1ca9b9279 100644 --- a/src/Python/qsharp-core/qsharp/loader.py +++ b/src/Python/qsharp-core/qsharp/loader.py @@ -127,22 +127,23 @@ def trace(self, **kwargs) -> Any: """ return qsharp.client.trace(self, **kwargs) - def as_qir(self) -> pqp.QirModule: + def as_qir(self) -> bytes: + """ + Returns the QIR bitcode representation of the callable, + assuming the callable is an entry point. + """ if getattr(pqp, "failed_with", None) is not None: raise pqp.failed_with - - # NB: Cannot load directly from bytes due to a missing feature in - # the llvm-ir crate that causes a similarly missing feature in - # pyqir.parser. f = tf.NamedTemporaryFile(delete=False, suffix='.bc') f.close() - bitcode = qsharp.client.compile_to_qir(self, output=f.name) - module = pqp.QirModule(f.name) + qsharp.client.compile_to_qir(self, output=f.name) + with open(f.name, "rb") as bitcode_file: + bitcode = bitcode_file.read() try: os.unlink(f.name) except: pass - return module + return bitcode class QSharpModule(ModuleType): _qs_name : str From 36f2ebffe60bf66261435c4dad99e96d47c833f2 Mon Sep 17 00:00:00 2001 From: Scott Carda Date: Fri, 11 Mar 2022 14:22:30 -0800 Subject: [PATCH 35/51] changed forceQIR to generateQIR --- src/AzureClient/EntryPoint/EntryPointGenerator.cs | 4 ++-- src/AzureClient/EntryPoint/IEntryPointGenerator.cs | 4 ++-- src/Core/Compiler/CompilerService.cs | 12 ++++++------ src/Core/Compiler/ICompilerService.cs | 2 +- src/Kernel/Magic/QirMagic.cs | 2 +- src/Tests/AzureClientEntryPointTests.cs | 4 ++-- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/AzureClient/EntryPoint/EntryPointGenerator.cs b/src/AzureClient/EntryPoint/EntryPointGenerator.cs index 881591814b..87540a5fb8 100644 --- a/src/AzureClient/EntryPoint/EntryPointGenerator.cs +++ b/src/AzureClient/EntryPoint/EntryPointGenerator.cs @@ -81,7 +81,7 @@ public EntryPointGenerator( /// public IEntryPoint Generate(string operationName, string? executionTarget, - RuntimeCapability? runtimeCapability = null, bool forceQir = false) + RuntimeCapability? runtimeCapability = null, bool generateQir = false) { Logger?.LogDebug($"Generating entry point: operationName={operationName}, executionTarget={executionTarget}"); @@ -154,7 +154,7 @@ public IEntryPoint Generate(string operationName, string? executionTarget, EntryPointAssemblyInfo = Compiler.BuildEntryPoint( operationInfo, compilerMetadata, logger, Path.Combine(Workspace.CacheFolder, "__entrypoint__.dll"), executionTarget, runtimeCapability, - forceQir: forceQir); + generateQir: generateQir); if (EntryPointAssemblyInfo == null || logger.HasErrors) { Logger?.LogError($"Error compiling entry point for operation {operationName}."); diff --git a/src/AzureClient/EntryPoint/IEntryPointGenerator.cs b/src/AzureClient/EntryPoint/IEntryPointGenerator.cs index ec70adf520..ea1d3a308b 100644 --- a/src/AzureClient/EntryPoint/IEntryPointGenerator.cs +++ b/src/AzureClient/EntryPoint/IEntryPointGenerator.cs @@ -40,9 +40,9 @@ public interface IEntryPointGenerator /// The name of the operation to wrap in an entry point. /// The intended execution target for the compiled entry point. /// The runtime capabilities of the intended execution target. - /// When true, uses QIR to generate the entry point. + /// When true, uses QIR to generate the entry point. /// The generated entry point. public IEntryPoint Generate(string operationName, string? executionTarget, - RuntimeCapability? runtimeCapabilities = null, bool forceQir = false); + RuntimeCapability? runtimeCapabilities = null, bool generateQir = false); } } diff --git a/src/Core/Compiler/CompilerService.cs b/src/Core/Compiler/CompilerService.cs index a2067ca02e..36fef9f9ea 100644 --- a/src/Core/Compiler/CompilerService.cs +++ b/src/Core/Compiler/CompilerService.cs @@ -150,7 +150,7 @@ public IEnumerable IdentifyElements(string source) /// public AssemblyInfo? BuildEntryPoint(OperationInfo operation, CompilerMetadata metadatas, QSharpLogger logger, string dllName, string? executionTarget = null, - RuntimeCapability? runtimeCapability = null, bool forceQir = false) + RuntimeCapability? runtimeCapability = null, bool generateQir = false) { var signature = operation.Header.PrintSignature(); var argumentTuple = SyntaxTreeToQsharp.ArgumentTuple(operation.Header.ArgumentTuple, type => type.ToString(), symbolsOnly: true); @@ -167,7 +167,7 @@ public IEnumerable IdentifyElements(string source) }}"; var sources = new Dictionary() {{ entryPointUri, entryPointSnippet }}.ToImmutableDictionary(); - return BuildAssembly(sources, metadatas, logger, dllName, compileAsExecutable: true, executionTarget, runtimeCapability, regenerateAll: true, forceQir: forceQir); + return BuildAssembly(sources, metadatas, logger, dllName, compileAsExecutable: true, executionTarget, runtimeCapability, regenerateAll: true, generateQir: generateQir); } /// @@ -218,13 +218,13 @@ string WrapInNamespace(Snippet s) => /// /// The resulting assembly info will contain QIR instead of a Q# /// syntax if is non-null or - /// is set. QIR generation requires at + /// is set. QIR generation requires at /// least one valid entry point to be defined. /// private AssemblyInfo? BuildAssembly(ImmutableDictionary sources, CompilerMetadata metadata, QSharpLogger logger, string dllName, bool compileAsExecutable, string? executionTarget, RuntimeCapability? runtimeCapability = null, bool regenerateAll = false, - bool forceQir = false) + bool generateQir = false) { logger.LogDebug($"Compiling the following Q# files: {string.Join(",", sources.Keys.Select(f => f.LocalPath))}"); @@ -270,7 +270,7 @@ string WrapInNamespace(Snippet s) => List? manifestResources = null; Stream? qirStream = null; - if (string.IsNullOrEmpty(executionTarget) && !forceQir) + if (string.IsNullOrEmpty(executionTarget) && !generateQir) { // Generate the assembly from the C# compilation: var syntaxTree = new QsCompilation(fromSources.ToImmutableArray(), qsCompilation.EntryPoints); @@ -309,7 +309,7 @@ string WrapInNamespace(Snippet s) => generator.Emit(bcFile, emitBitcode: true); qirStream = File.OpenRead(bcFile); } - else if (forceQir) + else if (generateQir) { // If we made it here, QIR was enabled, but we didn't have // any valid entry points. diff --git a/src/Core/Compiler/ICompilerService.cs b/src/Core/Compiler/ICompilerService.cs index 9ecad1b6bb..bb054aea21 100644 --- a/src/Core/Compiler/ICompilerService.cs +++ b/src/Core/Compiler/ICompilerService.cs @@ -25,7 +25,7 @@ public interface ICompilerService /// by the provided object. /// AssemblyInfo BuildEntryPoint(OperationInfo operation, CompilerMetadata metadatas, QSharpLogger logger, string dllName, string executionTarget = null, - RuntimeCapability runtimeCapability = null, bool forceQir = false); + RuntimeCapability runtimeCapability = null, bool generateQir = false); /// /// Builds the corresponding .net core assembly from the code in the given Q# Snippets. diff --git a/src/Kernel/Magic/QirMagic.cs b/src/Kernel/Magic/QirMagic.cs index 74e3e3f3d4..062590984e 100644 --- a/src/Kernel/Magic/QirMagic.cs +++ b/src/Kernel/Magic/QirMagic.cs @@ -70,7 +70,7 @@ public async Task RunAsync(string input, IChannel channel) IEntryPoint? entryPoint; try { - entryPoint = EntryPointGenerator.Generate(name, null, RuntimeCapability.FullComputation, forceQir: true); + entryPoint = EntryPointGenerator.Generate(name, null, RuntimeCapability.FullComputation, generateQir: true); } catch (TaskCanceledException tce) { diff --git a/src/Tests/AzureClientEntryPointTests.cs b/src/Tests/AzureClientEntryPointTests.cs index 5b96a5b262..3783fc41b4 100644 --- a/src/Tests/AzureClientEntryPointTests.cs +++ b/src/Tests/AzureClientEntryPointTests.cs @@ -86,7 +86,7 @@ public async Task FromSnippet() public async Task QIRSubmission() { var entryPointGenerator = Init("Workspace", new string[] { SNIPPETS.HelloQ }); - var entryPoint = entryPointGenerator.Generate("HelloQ", null, forceQir: true); + var entryPoint = entryPointGenerator.Generate("HelloQ", null, generateQir: true); Assert.IsNotNull(entryPoint); var job = await entryPoint.SubmitAsync( @@ -99,7 +99,7 @@ public async Task QIRSubmission() public async Task ValidParameterTypes() { var entryPointGenerator = Init("Workspace", new string[] { SNIPPETS.ValidParameterTypes }); - var entryPoint = entryPointGenerator.Generate("UseValidParameterTypes", null, forceQir: true); + var entryPoint = entryPointGenerator.Generate("UseValidParameterTypes", null, generateQir: true); Assert.IsNotNull(entryPoint); From e6db0d4dafca0f6eebfd18fc101398fa738bb472 Mon Sep 17 00:00:00 2001 From: Scott Carda Date: Fri, 11 Mar 2022 14:43:17 -0800 Subject: [PATCH 36/51] Added doc comments to the mock QIR submitter. --- src/AzureClient/Mocks/MockQIRSubmitter.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/AzureClient/Mocks/MockQIRSubmitter.cs b/src/AzureClient/Mocks/MockQIRSubmitter.cs index adf54bc5ca..f966ed4cbb 100644 --- a/src/AzureClient/Mocks/MockQIRSubmitter.cs +++ b/src/AzureClient/Mocks/MockQIRSubmitter.cs @@ -19,6 +19,10 @@ internal class MockQIRSubmitter : IQirSubmitter private IReadOnlyList ExpectedArguments = new List(); + /// + /// Creates a Mock QIR Submitter, with expected entry point arguments to the SubmitAsync method. + /// + /// The expected entry point arguments to the SubmitAsync method. public MockQIRSubmitter(IReadOnlyList expectedArguments) { this.ExpectedArguments = expectedArguments; @@ -55,6 +59,14 @@ private bool IsEqualToExpected(IReadOnlyList arguments) .All(tup => tup.fst.Name == tup.snd.Name && IsArgumentValueEqual(tup.fst.Value, tup.snd.Value)); } + /// + /// Mocks a SubmitAsync call, checking that the given argumentsc> are a match to the expected arguments for this mock submitter. + /// + /// The QIR stream for the entry point. + /// The name of the entry point. + /// The arguments to the entry point. These will be compared against the expected arguments. + /// Additional submission options. + /// public Task SubmitAsync(Stream qir, string entryPoint, IReadOnlyList arguments, SubmissionOptions options) { var job = new MockCloudJob(); From 03cbc4c068e6487dfced9b3702368ddb7b2f16f1 Mon Sep 17 00:00:00 2001 From: Scott Carda Date: Fri, 11 Mar 2022 14:47:20 -0800 Subject: [PATCH 37/51] comment --- src/Core/Compiler/CompilerService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Core/Compiler/CompilerService.cs b/src/Core/Compiler/CompilerService.cs index 36fef9f9ea..c7865f5076 100644 --- a/src/Core/Compiler/CompilerService.cs +++ b/src/Core/Compiler/CompilerService.cs @@ -303,7 +303,7 @@ string WrapInNamespace(Snippet s) => using var generator = new Generator(transformed); generator.Apply(); - // write generated QIR to disk + // Write generated QIR to disk. var tempPath = Path.GetTempPath(); var bcFile = CompilationLoader.GeneratedFile(Path.Combine(tempPath, Path.GetRandomFileName()), tempPath, ".bc", ""); generator.Emit(bcFile, emitBitcode: true); From 17aa9ba36c43ff9c66ecdc30c5690165865370a6 Mon Sep 17 00:00:00 2001 From: Scott Carda Date: Fri, 11 Mar 2022 15:18:12 -0800 Subject: [PATCH 38/51] Don't check ActiveTarget in AzureClient.cs --- src/AzureClient/AzureClient.cs | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/src/AzureClient/AzureClient.cs b/src/AzureClient/AzureClient.cs index ce0cf434f0..2ea9e406d1 100644 --- a/src/AzureClient/AzureClient.cs +++ b/src/AzureClient/AzureClient.cs @@ -19,6 +19,8 @@ using Microsoft.Jupyter.Core; using Microsoft.Quantum.IQSharp.Common; using Microsoft.Quantum.IQSharp.Jupyter; +using Microsoft.Quantum.Runtime; +using Microsoft.Quantum.Runtime.Submitters; using Microsoft.Quantum.Simulation.Common; namespace Microsoft.Quantum.IQSharp.AzureClient @@ -349,29 +351,21 @@ private async Task SubmitOrExecuteJobAsync( // but both have a SubmitAsync method that returns an IQuantumMachineJob. // Thus, we can branch on whether we need a QIR submitter or a translator, // but can use the same task object to represent both return values. - Task? jobTask = null; - if (this.ActiveTarget.TargetId.StartsWith(MicrosoftSimulator)) + Task? jobTask = null; + if (SubmitterFactory.QirSubmitter(this.ActiveTarget.TargetId, this.ActiveWorkspace, this.StorageConnectionString) is IQirSubmitter submitter) { - var submitter = SubmitterFactory.QirSubmitter(this.ActiveTarget.TargetId, this.ActiveWorkspace, this.StorageConnectionString); - if (submitter == null) - { - // We should never get here, since ActiveTarget should have already been validated at the time it was set. - channel?.Stderr($"Unexpected error while preparing job for execution on target {ActiveTarget.TargetId}."); - return AzureClientError.InvalidTarget.ToExecutionResult(); - } jobTask = entryPoint.SubmitAsync(submitter, submissionContext); } - else + else if (AzureFactory.CreateMachine(this.ActiveWorkspace, this.ActiveTarget.TargetId, this.StorageConnectionString) is IQuantumMachine machine) { - var machine = AzureFactory.CreateMachine(this.ActiveWorkspace, this.ActiveTarget.TargetId, this.StorageConnectionString); - if (machine == null) - { - // We should never get here, since ActiveTarget should have already been validated at the time it was set. - channel?.Stderr($"Unexpected error while preparing job for execution on target {ActiveTarget.TargetId}."); - return AzureClientError.InvalidTarget.ToExecutionResult(); - } jobTask = entryPoint.SubmitAsync(machine, submissionContext); } + else + { + // We should never get here, since ActiveTarget should have already been validated at the time it was set. + channel?.Stderr($"Unexpected error while preparing job for execution on target {ActiveTarget.TargetId}."); + return AzureClientError.InvalidTarget.ToExecutionResult(); + } Logger.LogDebug("About to submit entry point for {OperationName}.", submissionContext.OperationName); var job = await jobTask; From 352dfdc1010bc73b94f5c67502576f1087082026 Mon Sep 17 00:00:00 2001 From: Scott Carda Date: Fri, 11 Mar 2022 15:32:04 -0800 Subject: [PATCH 39/51] Added GitHub issue links to ToDos. --- src/Kernel/Magic/QirMagic.cs | 1 + src/Tests/AzureClientTests.cs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/Kernel/Magic/QirMagic.cs b/src/Kernel/Magic/QirMagic.cs index 062590984e..8c6f6c58a1 100644 --- a/src/Kernel/Magic/QirMagic.cs +++ b/src/Kernel/Magic/QirMagic.cs @@ -50,6 +50,7 @@ or function name that has been defined either in the notebook or in a Q# file in // TODO: EntryPointGenerator might should move out of the Azure Client // project. + // GitHub Issue: https://github.com/microsoft/iqsharp/issues/610 public IEntryPointGenerator EntryPointGenerator { get; } /// diff --git a/src/Tests/AzureClientTests.cs b/src/Tests/AzureClientTests.cs index 1b101e96b1..d084a16012 100644 --- a/src/Tests/AzureClientTests.cs +++ b/src/Tests/AzureClientTests.cs @@ -181,6 +181,7 @@ public void TestAllTargets() // 2 targets per provider: mock and simulator. // TODO: uncomment once there is a microsoft.mock target + // GitHub Issue: https://github.com/microsoft/iqsharp/issues/609 //Assert.AreEqual(2 * Enum.GetNames(typeof(AzureProvider)).Length, targets.Count()); // set each target, which will load the corresponding package From e4d51de48041b4fcdb8c82ae408d691a7af0810f Mon Sep 17 00:00:00 2001 From: Scott Carda Date: Fri, 11 Mar 2022 15:37:27 -0800 Subject: [PATCH 40/51] removed external reference to Log --- src/AzureClient/Extensions.cs | 2 +- src/Kernel/Magic/QirMagic.cs | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/AzureClient/Extensions.cs b/src/AzureClient/Extensions.cs index bc5f7e3001..fec660b6f6 100644 --- a/src/AzureClient/Extensions.cs +++ b/src/AzureClient/Extensions.cs @@ -91,7 +91,7 @@ internal static bool Matches(this CloudJob job, string filter) => /// Writes an exception to a logger and emits it to the stderr stream /// of a Jupyter display channel. /// - public static void Log(this Exception ex, IChannel? channel, ILogger? logger, string msg = "") + internal static void Log(this Exception ex, IChannel? channel, ILogger? logger, string msg = "") { logger?.LogError(ex, msg); channel?.Stderr(msg); diff --git a/src/Kernel/Magic/QirMagic.cs b/src/Kernel/Magic/QirMagic.cs index 8c6f6c58a1..b925e98039 100644 --- a/src/Kernel/Magic/QirMagic.cs +++ b/src/Kernel/Magic/QirMagic.cs @@ -79,7 +79,10 @@ public async Task RunAsync(string input, IChannel channel) } catch (CompilationErrorsException e) { - e.Log(channel, this.Logger, $"The Q# operation {name} could not be compiled as an entry point for job execution."); + var msg = $"The Q# operation {name} could not be compiled as an entry point for job execution."; + this.Logger?.LogError(e, msg); + channel?.Stderr(msg); + channel?.Stderr(e.Message); foreach (var message in e.Errors) channel?.Stderr(message); return AzureClientError.InvalidEntryPoint.ToExecutionResult(); } From e1080cfc89493c86a1234240c18d297b10bf1516 Mon Sep 17 00:00:00 2001 From: Scott Carda Date: Fri, 11 Mar 2022 16:36:33 -0800 Subject: [PATCH 41/51] Added EntryPointNamespaceName to CompilerService. --- src/AzureClient/EntryPoint/EntryPoint.cs | 2 +- src/Core/Compiler/CompilerService.cs | 7 ++++++- src/Tests/AzureClientEntryPointTests.cs | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/AzureClient/EntryPoint/EntryPoint.cs b/src/AzureClient/EntryPoint/EntryPoint.cs index 52403e63fc..daa37268c3 100644 --- a/src/AzureClient/EntryPoint/EntryPoint.cs +++ b/src/AzureClient/EntryPoint/EntryPoint.cs @@ -199,7 +199,7 @@ public Task SubmitAsync(IQirSubmitter submitter, AzureSubmis && method.GetParameters()[2].ParameterType == typeof(IReadOnlyList) && method.GetParameters()[3].ParameterType == typeof(SubmissionOptions) ); - var submitParameters = new object[] { QirStream!, $"ENTRYPOINT__{submissionContext.OperationName}", entryPointInput, options }; + var submitParameters = new object[] { QirStream!, $"{CompilerService.EntryPointNamespaceName}__{submissionContext.OperationName}", entryPointInput, options }; return (Task)submitMethod.Invoke(submitter, submitParameters); } } diff --git a/src/Core/Compiler/CompilerService.cs b/src/Core/Compiler/CompilerService.cs index c7865f5076..7bda88746c 100644 --- a/src/Core/Compiler/CompilerService.cs +++ b/src/Core/Compiler/CompilerService.cs @@ -56,6 +56,11 @@ public class Settings public string? AutoOpenNamespaces { get; set; } } + /// + /// The name of the generated namespace for the entry point. + /// + public static string EntryPointNamespaceName = "ENTRYPOINT"; + /// public IDictionary AutoOpenNamespaces { get; set; } = new Dictionary { @@ -156,7 +161,7 @@ public IEnumerable IdentifyElements(string source) var argumentTuple = SyntaxTreeToQsharp.ArgumentTuple(operation.Header.ArgumentTuple, type => type.ToString(), symbolsOnly: true); var entryPointUri = new Uri(Path.GetFullPath(Path.Combine("/", $"entrypoint.qs"))); - var entryPointSnippet = @$"namespace ENTRYPOINT + var entryPointSnippet = @$"namespace {EntryPointNamespaceName} {{ open {operation.Header.QualifiedName.Namespace}; @{BuiltIn.EntryPoint.FullName}() diff --git a/src/Tests/AzureClientEntryPointTests.cs b/src/Tests/AzureClientEntryPointTests.cs index 3783fc41b4..2d254b64e7 100644 --- a/src/Tests/AzureClientEntryPointTests.cs +++ b/src/Tests/AzureClientEntryPointTests.cs @@ -53,7 +53,7 @@ public async Task FromSnippet() // syntax trees that we need to generate classical control from. .HasResource(DotnetCoreDll.SyntaxTreeResourceName) // Make sure that the two particular operations we expect are both there. - .HasOperation("ENTRYPOINT", "HelloQ") + .HasOperation(CompilerService.EntryPointNamespaceName, "HelloQ") .HasOperation(Snippets.SNIPPETS_NAMESPACE, "HelloQ") // Since HelloQ calls Message, that function should also be regenerated. .HasOperation("Microsoft.Quantum.Intrinsic", "Message"); From ec54759fbe04a2b290433ae8128cdda7cd1a6586 Mon Sep 17 00:00:00 2001 From: Scott Carda Date: Wed, 16 Mar 2022 17:16:40 -0700 Subject: [PATCH 42/51] reworked tests --- src/Tests/AzureClientEntryPointTests.cs | 304 +++++++++++++++++++++--- src/Tests/SNIPPETS.cs | 137 ++++++++++- 2 files changed, 408 insertions(+), 33 deletions(-) diff --git a/src/Tests/AzureClientEntryPointTests.cs b/src/Tests/AzureClientEntryPointTests.cs index 2d254b64e7..2fddccb57d 100644 --- a/src/Tests/AzureClientEntryPointTests.cs +++ b/src/Tests/AzureClientEntryPointTests.cs @@ -105,14 +105,14 @@ public async Task ValidParameterTypes() var validArguments = new Dictionary() { - { new Argument("myBool", new ArgumentValue.Bool(true)), "\"true\"" }, - { new Argument("myDouble", new ArgumentValue.Double(1.2)), "\"1.2\"" }, - { new Argument("myInt", new ArgumentValue.Int(2)), "\"2\"" }, - { new Argument("myStr", new ArgumentValue.String("\"Hello\"")), "\"Hello\"" }, - { new Argument("myPauli", new ArgumentValue.Pauli(Pauli.PauliX)), "\"PauliX\"" }, - { new Argument("myResult", new ArgumentValue.Result(Result.One)) , "\"1\"" }, - { new Argument("innerInt", new ArgumentValue.Int(7)) , "\"7\"" }, - { new Argument("innerDouble", new ArgumentValue.Double(6.4)) , "\"6.4\"" } + [new Argument("myBool", new ArgumentValue.Bool(true))] = "\"true\"", + [new Argument("myDouble", new ArgumentValue.Double(1.2))] = "\"1.2\"", + [new Argument("myInt", new ArgumentValue.Int(2))] = "\"2\"", + [new Argument("myStr", new ArgumentValue.String("\"Hello\""))] = "\"Hello\"", + [new Argument("myPauli", new ArgumentValue.Pauli(Pauli.PauliX))] = "\"PauliX\"", + [new Argument("myResult", new ArgumentValue.Result(Result.One))] = "\"1\"", + [new Argument("innerInt", new ArgumentValue.Int(7))] = "\"7\"", + [new Argument("innerDouble", new ArgumentValue.Double(6.4))] = "\"6.4\"" }; var job = await entryPoint.SubmitAsync( @@ -125,48 +125,292 @@ public async Task ValidParameterTypes() } [TestMethod] - public async Task InvalidParameterTypes() + public async Task ValidBoolParameter() { - var entryPointGenerator = Init("Workspace", new string[] { SNIPPETS.InvalidParameterTypes }); + var entryPointGenerator = Init("Workspace", new string[] { SNIPPETS.ValidBoolParameter }); + var entryPoint = entryPointGenerator.Generate("UseBoolType", null, generateQir: true); + + Assert.IsNotNull(entryPoint); + var job = await entryPoint.SubmitAsync( + new MockQIRSubmitter(new List() { new Argument("myBool", new ArgumentValue.Bool(true)) }), + new AzureSubmissionContext() + { + InputParameters = new Dictionary { ["myBool"] = "\"true\"" } + }); + Assert.IsNotNull(job); + } + + [TestMethod] + public async Task ValidDoubleParameter() + { + var entryPointGenerator = Init("Workspace", new string[] { SNIPPETS.ValidDoubleParameter }); + var entryPoint = entryPointGenerator.Generate("UseDoubleType", null, generateQir: true); + + Assert.IsNotNull(entryPoint); + var job = await entryPoint.SubmitAsync( + new MockQIRSubmitter(new List() { new Argument("myDouble", new ArgumentValue.Double(1.2)) }), + new AzureSubmissionContext() + { + InputParameters = new Dictionary { ["myDouble"] = "\"1.2\"" } + }); + Assert.IsNotNull(job); + } + + [TestMethod] + public async Task ValidIntParameter() + { + var entryPointGenerator = Init("Workspace", new string[] { SNIPPETS.ValidIntParameter }); + var entryPoint = entryPointGenerator.Generate("UseIntType", null, generateQir: true); + + Assert.IsNotNull(entryPoint); + var job = await entryPoint.SubmitAsync( + new MockQIRSubmitter(new List() { new Argument("myInt", new ArgumentValue.Int(2)) }), + new AzureSubmissionContext() + { + InputParameters = new Dictionary { ["myInt"] = "\"2\"" } + }); + Assert.IsNotNull(job); + } + + [TestMethod] + public async Task ValidStringParameter() + { + var entryPointGenerator = Init("Workspace", new string[] { SNIPPETS.ValidStringParameter }); + var entryPoint = entryPointGenerator.Generate("UseStringType", null, generateQir: true); + + Assert.IsNotNull(entryPoint); + var job = await entryPoint.SubmitAsync( + new MockQIRSubmitter(new List() { new Argument("myStr", new ArgumentValue.String("\"Hello\"")) }), + new AzureSubmissionContext() + { + InputParameters = new Dictionary { ["myStr"] = "\"Hello\"" } + }); + Assert.IsNotNull(job); + } + + [TestMethod] + public async Task ValidPauliParameter() + { + var entryPointGenerator = Init("Workspace", new string[] { SNIPPETS.ValidPauliParameter }); + var entryPoint = entryPointGenerator.Generate("UsePauliType", null, generateQir: true); + + Assert.IsNotNull(entryPoint); + var job = await entryPoint.SubmitAsync( + new MockQIRSubmitter(new List() { new Argument("myPauli", new ArgumentValue.Pauli(Pauli.PauliX)) }), + new AzureSubmissionContext() + { + InputParameters = new Dictionary { ["myPauli"] = "\"PauliX\"" } + }); + Assert.IsNotNull(job); + } + + [TestMethod] + public async Task ValidResultParameter() + { + var entryPointGenerator = Init("Workspace", new string[] { SNIPPETS.ValidResultParameter }); + var entryPoint = entryPointGenerator.Generate("UseResultType", null, generateQir: true); + + Assert.IsNotNull(entryPoint); + var job = await entryPoint.SubmitAsync( + new MockQIRSubmitter(new List() { new Argument("myResult", new ArgumentValue.Result(Result.One)) }), + new AzureSubmissionContext() + { + InputParameters = new Dictionary { ["myResult"] = "\"1\"" } + }); + Assert.IsNotNull(job); + } + + [TestMethod] + public async Task ValidTupleParameters() + { + var entryPointGenerator = Init("Workspace", new string[] { SNIPPETS.ValidTupleParameters }); + var entryPoint = entryPointGenerator.Generate("UseTupleType", null, generateQir: true); + + var validArguments = new Dictionary() + { + [new Argument("innerInt", new ArgumentValue.Int(7))] = "\"7\"", + [new Argument("innerDouble", new ArgumentValue.Double(6.4))] = "\"6.4\"", + [new Argument("innerString", new ArgumentValue.String("\"Hello\""))] = "\"Hello\"", + [new Argument("innerResult", new ArgumentValue.Result(Result.One))] = "\"1\"", + }; + + var job = await entryPoint.SubmitAsync( + new MockQIRSubmitter(validArguments.Select(x => x.Key).ToList()), + new AzureSubmissionContext() + { + InputParameters = validArguments.ToDictionary(x => x.Key.Name, x => x.Value) + }); + Assert.IsNotNull(job); + } + + [TestMethod] + public async Task InvalidUnitParameters() + { + var entryPointGenerator = Init("Workspace", new string[] { SNIPPETS.InvalidUnitParameters }); - var unitEntryPoint = entryPointGenerator.Generate("UseUnitType", null); - Assert.IsNotNull(unitEntryPoint); - await Assert.ThrowsExceptionAsync(() => unitEntryPoint.SubmitAsync( + var entryPoint = entryPointGenerator.Generate("UseUnitType", null); + Assert.IsNotNull(entryPoint); + await Assert.ThrowsExceptionAsync(() => entryPoint.SubmitAsync( + new MockQIRSubmitter(new List()), + new AzureSubmissionContext() + { + InputParameters = new Dictionary { ["myUnit"] = "\"()\"" } + })); + + entryPoint = entryPointGenerator.Generate("UseUnitTypeFirst", null); + Assert.IsNotNull(entryPoint); + await Assert.ThrowsExceptionAsync(() => entryPoint.SubmitAsync( new MockQIRSubmitter(new List()), new AzureSubmissionContext() { - InputParameters = new[] { ("myUnit", "\"()\"") }.ToDictionary(x => x.Item1, x => x.Item2) + InputParameters = new Dictionary + { + ["myUnit"] = "\"()\"", + ["myInt"] = "\"2\"", + ["myBool"] = "\"true\"" + } })); - var arrayEntryPoint = entryPointGenerator.Generate("UseArrayType", null); - Assert.IsNotNull(arrayEntryPoint); - await Assert.ThrowsExceptionAsync(() => arrayEntryPoint.SubmitAsync( + entryPoint = entryPointGenerator.Generate("UseUnitTypeMiddle", null); + Assert.IsNotNull(entryPoint); + await Assert.ThrowsExceptionAsync(() => entryPoint.SubmitAsync( + new MockQIRSubmitter(new List()), + new AzureSubmissionContext() + { + InputParameters = new Dictionary + { + ["myInt"] = "\"2\"", + ["myUnit"] = "\"()\"", + ["myBool"] = "\"true\"" + } + })); + + entryPoint = entryPointGenerator.Generate("UseUnitTypeLast", null); + Assert.IsNotNull(entryPoint); + await Assert.ThrowsExceptionAsync(() => entryPoint.SubmitAsync( + new MockQIRSubmitter(new List()), + new AzureSubmissionContext() + { + InputParameters = new Dictionary + { + ["myInt"] = "\"2\"", + ["myBool"] = "\"true\"", + ["myUnit"] = "\"()\"" + } + })); + } + + [TestMethod] + public async Task InvalidArrayParameters() + { + var entryPointGenerator = Init("Workspace", new string[] { SNIPPETS.InvalidArrayParameters }); + + var entryPoint = entryPointGenerator.Generate("UseArrayType", null); + Assert.IsNotNull(entryPoint); + await Assert.ThrowsExceptionAsync(() => entryPoint.SubmitAsync( new MockQIRSubmitter(new List()), new AzureSubmissionContext() { - InputParameters = new[] { ("myArray", "\"[2, 4, 8]\"") }.ToDictionary(x => x.Item1, x => x.Item2) + InputParameters = new Dictionary { ["myArray"] = "\"[2, 4, 8]\"" } })); - var rangeEntryPoint = entryPointGenerator.Generate("UseRangeType", null); - Assert.IsNotNull(rangeEntryPoint); - await Assert.ThrowsExceptionAsync(() => rangeEntryPoint.SubmitAsync( + entryPoint = entryPointGenerator.Generate("UseArrayTypeFirst", null); + Assert.IsNotNull(entryPoint); + await Assert.ThrowsExceptionAsync(() => entryPoint.SubmitAsync( new MockQIRSubmitter(new List()), new AzureSubmissionContext() { - InputParameters = new[] { ("myRange", "\"0..2..10\"") }.ToDictionary(x => x.Item1, x => x.Item2) + InputParameters = new Dictionary + { + ["myArray"] = "\"[2, 4, 8]\"", + ["myInt"] = "\"2\"", + ["myBool"] = "\"true\"" + } })); - var embeddedUnitEntryPoint = entryPointGenerator.Generate("UseEmbeddedUnitType", null); - Assert.IsNotNull(embeddedUnitEntryPoint); - await Assert.ThrowsExceptionAsync(() => embeddedUnitEntryPoint.SubmitAsync( + entryPoint = entryPointGenerator.Generate("UseArrayTypeMiddle", null); + Assert.IsNotNull(entryPoint); + await Assert.ThrowsExceptionAsync(() => entryPoint.SubmitAsync( + new MockQIRSubmitter(new List()), + new AzureSubmissionContext() + { + InputParameters = new Dictionary + { + ["myInt"] = "\"2\"", + ["myArray"] = "\"[2, 4, 8]\"", + ["myBool"] = "\"true\"" + } + })); + + entryPoint = entryPointGenerator.Generate("UseArrayTypeLast", null); + Assert.IsNotNull(entryPoint); + await Assert.ThrowsExceptionAsync(() => entryPoint.SubmitAsync( + new MockQIRSubmitter(new List()), + new AzureSubmissionContext() + { + InputParameters = new Dictionary + { + ["myInt"] = "\"2\"", + ["myBool"] = "\"true\"", + ["myArray"] = "\"[2, 4, 8]\"" + } + })); + } + + [TestMethod] + public async Task InvalidRangeParameters() + { + var entryPointGenerator = Init("Workspace", new string[] { SNIPPETS.InvalidRangeParameters }); + + var entryPoint = entryPointGenerator.Generate("UseRangeType", null); + Assert.IsNotNull(entryPoint); + await Assert.ThrowsExceptionAsync(() => entryPoint.SubmitAsync( + new MockQIRSubmitter(new List()), + new AzureSubmissionContext() + { + InputParameters = new Dictionary { ["myRange"] = "\"0..2..10\"" } + })); + + entryPoint = entryPointGenerator.Generate("UseRangeTypeFirst", null); + Assert.IsNotNull(entryPoint); + await Assert.ThrowsExceptionAsync(() => entryPoint.SubmitAsync( + new MockQIRSubmitter(new List()), + new AzureSubmissionContext() + { + InputParameters = new Dictionary + { + ["myRange"] = "\"0..2..10\"", + ["myInt"] = "\"2\"", + ["myBool"] = "\"true\"" + } + })); + + entryPoint = entryPointGenerator.Generate("UseRangeTypeMiddle", null); + Assert.IsNotNull(entryPoint); + await Assert.ThrowsExceptionAsync(() => entryPoint.SubmitAsync( + new MockQIRSubmitter(new List()), + new AzureSubmissionContext() + { + InputParameters = new Dictionary + { + ["myInt"] = "\"2\"", + ["myRange"] = "\"0..2..10\"", + ["myBool"] = "\"true\"" + } + })); + + entryPoint = entryPointGenerator.Generate("UseRangeTypeLast", null); + Assert.IsNotNull(entryPoint); + await Assert.ThrowsExceptionAsync(() => entryPoint.SubmitAsync( new MockQIRSubmitter(new List()), new AzureSubmissionContext() { - InputParameters = new[] { - ("myInt", "\"2\""), - ("myUnit", "\"()\""), - ("myBool", "\"true\"") - }.ToDictionary(x => x.Item1, x => x.Item2) + InputParameters = new Dictionary + { + ["myInt"] = "\"2\"", + ["myBool"] = "\"true\"", + ["myRange"] = "\"0..2..10\"" + } })); } diff --git a/src/Tests/SNIPPETS.cs b/src/Tests/SNIPPETS.cs index aac8d6b48b..8730ca2cac 100644 --- a/src/Tests/SNIPPETS.cs +++ b/src/Tests/SNIPPETS.cs @@ -378,7 +378,85 @@ operation UseValidParameterTypes( } "; - public static string InvalidParameterTypes = + public static string ValidBoolParameter = +@" + operation UseBoolType( + myBool: Bool + ) : Result { + use q = Qubit(); + H(q); + return M(q); + } +"; + + public static string ValidDoubleParameter = +@" + operation UseDoubleType( + myDouble: Double + ) : Result { + use q = Qubit(); + H(q); + return M(q); + } +"; + + public static string ValidIntParameter = +@" + operation UseIntType( + myInt: Int + ) : Result { + use q = Qubit(); + H(q); + return M(q); + } +"; + + public static string ValidStringParameter = +@" + operation UseStringType( + myStr: String + ) : Result { + use q = Qubit(); + H(q); + return M(q); + } +"; + + public static string ValidPauliParameter = +@" + operation UsePauliType( + myPauli: Pauli + ) : Result { + use q = Qubit(); + H(q); + return M(q); + } +"; + + public static string ValidResultParameter = +@" + operation UseResultType( + myResult: Result + ) : Result { + use q = Qubit(); + H(q); + return M(q); + } +"; + + public static string ValidTupleParameters = +@" + operation UseTupleType( + (innerInt: Int, innerDouble: Double), + (innerString: String, innerResult: Result) + ) : Result { + use q = Qubit(); + H(q); + return M(q); + } +"; + + public static string InvalidUnitParameters = @" operation UseUnitType(myUnit: Unit) : Result { use q = Qubit(); @@ -386,24 +464,77 @@ operation UseUnitType(myUnit: Unit) : Result { return M(q); } + operation UseUnitTypeFirst(myUnit: Unit, myInt: Int, myBool: Bool) : Result { + use q = Qubit(); + H(q); + return M(q); + } + + operation UseUnitTypeMiddle(myInt: Int, myUnit: Unit, myBool: Bool) : Result { + use q = Qubit(); + H(q); + return M(q); + } + + operation UseUnitTypeLast(myInt: Int, myBool: Bool, myUnit: Unit) : Result { + use q = Qubit(); + H(q); + return M(q); + } +"; + + public static string InvalidArrayParameters = +@" operation UseArrayType(myArray: Int[]) : Result { use q = Qubit(); H(q); return M(q); } - operation UseRangeType(myRange: Range) : Result { + operation UseArrayTypeFirst(myArray: Int[], myInt: Int, myBool: Bool) : Result { + use q = Qubit(); + H(q); + return M(q); + } + + operation UseArrayTypeMiddle(myInt: Int, myArray: Int[], myBool: Bool) : Result { use q = Qubit(); H(q); return M(q); } - operation UseEmbeddedUnitType(myInt: Int, myUnit: Unit, myBool: Bool) : Result { + operation UseArrayTypeLast(myInt: Int, myBool: Bool, myArray: Int[]) : Result { use q = Qubit(); H(q); return M(q); } "; + public static string InvalidRangeParameters = +@" + operation UseRangeType(myRange: Range) : Result { + use q = Qubit(); + H(q); + return M(q); + } + + operation UseRangeTypeFirst(myRange: Range, myInt: Int, myBool: Bool) : Result { + use q = Qubit(); + H(q); + return M(q); + } + + operation UseRangeTypeMiddle(myInt: Int, myRange: Range, myBool: Bool) : Result { + use q = Qubit(); + H(q); + return M(q); + } + + operation UseRangeTypeLast(myInt: Int, myBool: Bool, myRange: Range) : Result { + use q = Qubit(); + H(q); + return M(q); + } +"; } } From 75c72e3e388dff6acdc6c9bc7e823c87ab00a0e7 Mon Sep 17 00:00:00 2001 From: Scott Carda Date: Wed, 16 Mar 2022 17:21:16 -0700 Subject: [PATCH 43/51] python changes --- src/Python/qsharp-core/qsharp/loader.py | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/Python/qsharp-core/qsharp/loader.py b/src/Python/qsharp-core/qsharp/loader.py index e1ca9b9279..ea88c9a071 100644 --- a/src/Python/qsharp-core/qsharp/loader.py +++ b/src/Python/qsharp-core/qsharp/loader.py @@ -18,16 +18,6 @@ from typing import Iterable, List, Optional, Any, Dict, Tuple -try: - import pyqir_parser as pqp -except ImportError as ex: - try: - import pyqir.parser as pqp - except ImportError: - class pqp: - failed_with = ex - QirModule = None - import logging logger = logging.getLogger(__name__) @@ -132,8 +122,6 @@ def as_qir(self) -> bytes: Returns the QIR bitcode representation of the callable, assuming the callable is an entry point. """ - if getattr(pqp, "failed_with", None) is not None: - raise pqp.failed_with f = tf.NamedTemporaryFile(delete=False, suffix='.bc') f.close() qsharp.client.compile_to_qir(self, output=f.name) From b4d075ccef220fcccc8486e3809555b7d746603d Mon Sep 17 00:00:00 2001 From: Scott Carda Date: Thu, 17 Mar 2022 17:47:04 -0700 Subject: [PATCH 44/51] EntryPointNamespaceName --- src/AzureClient/EntryPoint/EntryPoint.cs | 5 ++++- src/Core/Compiler/CompilerService.cs | 2 +- src/Tests/AzureClientEntryPointTests.cs | 3 ++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/AzureClient/EntryPoint/EntryPoint.cs b/src/AzureClient/EntryPoint/EntryPoint.cs index daa37268c3..5505335598 100644 --- a/src/AzureClient/EntryPoint/EntryPoint.cs +++ b/src/AzureClient/EntryPoint/EntryPoint.cs @@ -187,6 +187,9 @@ public Task SubmitAsync(IQirSubmitter submitter, AzureSubmis var options = SubmissionOptions.Default; options = options.With(submissionContext.FriendlyName, submissionContext.Shots, submissionContext.InputParams); + // The namespace must match the one found in the in CompilerService.cs in the Core project. + var entryPointNamespaceName = "ENTRYPOINT"; + // Find and invoke the method on IQirSubmitter that is declared as: // Task SubmitAsync(Stream qir, string entryPoint, IReadOnlyList arguments, SubmissionOptions submissionOptions) var submitMethod = typeof(IQirSubmitter) @@ -199,7 +202,7 @@ public Task SubmitAsync(IQirSubmitter submitter, AzureSubmis && method.GetParameters()[2].ParameterType == typeof(IReadOnlyList) && method.GetParameters()[3].ParameterType == typeof(SubmissionOptions) ); - var submitParameters = new object[] { QirStream!, $"{CompilerService.EntryPointNamespaceName}__{submissionContext.OperationName}", entryPointInput, options }; + var submitParameters = new object[] { QirStream!, $"{entryPointNamespaceName}__{submissionContext.OperationName}", entryPointInput, options }; return (Task)submitMethod.Invoke(submitter, submitParameters); } } diff --git a/src/Core/Compiler/CompilerService.cs b/src/Core/Compiler/CompilerService.cs index 7bda88746c..6504a0af68 100644 --- a/src/Core/Compiler/CompilerService.cs +++ b/src/Core/Compiler/CompilerService.cs @@ -59,7 +59,7 @@ public class Settings /// /// The name of the generated namespace for the entry point. /// - public static string EntryPointNamespaceName = "ENTRYPOINT"; + private static readonly string EntryPointNamespaceName = "ENTRYPOINT"; /// public IDictionary AutoOpenNamespaces { get; set; } = new Dictionary diff --git a/src/Tests/AzureClientEntryPointTests.cs b/src/Tests/AzureClientEntryPointTests.cs index 2fddccb57d..1a444cb160 100644 --- a/src/Tests/AzureClientEntryPointTests.cs +++ b/src/Tests/AzureClientEntryPointTests.cs @@ -53,7 +53,8 @@ public async Task FromSnippet() // syntax trees that we need to generate classical control from. .HasResource(DotnetCoreDll.SyntaxTreeResourceName) // Make sure that the two particular operations we expect are both there. - .HasOperation(CompilerService.EntryPointNamespaceName, "HelloQ") + // The namespace must match the one found in the in CompilerService.cs in the Core project. + .HasOperation("ENTRYPOINT", "HelloQ") .HasOperation(Snippets.SNIPPETS_NAMESPACE, "HelloQ") // Since HelloQ calls Message, that function should also be regenerated. .HasOperation("Microsoft.Quantum.Intrinsic", "Message"); From c9a5c41de745bc5ecc0daab5fb9891556644fa5a Mon Sep 17 00:00:00 2001 From: Scott Carda Date: Thu, 17 Mar 2022 17:47:18 -0700 Subject: [PATCH 45/51] PackageName --- src/AzureClient/AzureExecutionTarget.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/AzureClient/AzureExecutionTarget.cs b/src/AzureClient/AzureExecutionTarget.cs index b4f5dbf10d..9738231a5e 100644 --- a/src/AzureClient/AzureExecutionTarget.cs +++ b/src/AzureClient/AzureExecutionTarget.cs @@ -21,10 +21,7 @@ protected AzureExecutionTarget(string? targetId) public string? TargetId { get; } - public virtual string PackageName => - GetProvider(TargetId) == AzureProvider.Microsoft - ? "Microsoft.Quantum.Providers.Core" - : $"Microsoft.Quantum.Providers.{GetProvider(TargetId)}"; + public virtual string PackageName => $"Microsoft.Quantum.Providers.{GetProvider(TargetId)}"; public RuntimeCapability RuntimeCapability => GetProvider(TargetId) switch { From 2b5b8051752c10044714a3b1323dc258a93f97d1 Mon Sep 17 00:00:00 2001 From: Scott Carda Date: Thu, 17 Mar 2022 17:53:05 -0700 Subject: [PATCH 46/51] WIP --- src/Core/Compiler/CompilerService.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Core/Compiler/CompilerService.cs b/src/Core/Compiler/CompilerService.cs index 6504a0af68..a3122f06bf 100644 --- a/src/Core/Compiler/CompilerService.cs +++ b/src/Core/Compiler/CompilerService.cs @@ -147,6 +147,10 @@ public IEnumerable IdentifyElements(string source) IsExecutable = compileAsExecutable, AssemblyConstants = new Dictionary { [AssemblyConstants.ProcessorArchitecture] = executionTarget ?? string.Empty }, RuntimeCapability = runtimeCapability ?? RuntimeCapability.FullComputation, + // ToDo: The logic for determining if we should generate QIR should live in the SubmitterFactory as a + // static function, `TargetSupportsQir`. We should then be calling that static function here for + // PrepareQirGeneration instead of this logic. + // GitHub Issue: PrepareQirGeneration = executionTarget?.StartsWith("microsoft.simulator") ?? false }; var loaded = new CompilationLoader(_ => sources, _ => references, loadOptions, logger); From 86b8e9253ef42e3e0d4766d292059e8600c02c09 Mon Sep 17 00:00:00 2001 From: Scott Carda Date: Thu, 17 Mar 2022 17:55:37 -0700 Subject: [PATCH 47/51] Added ToDo for logic for PrepareQirGeneration to be moved to the SubmitterFactory. --- src/Core/Compiler/CompilerService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Core/Compiler/CompilerService.cs b/src/Core/Compiler/CompilerService.cs index a3122f06bf..be99017b09 100644 --- a/src/Core/Compiler/CompilerService.cs +++ b/src/Core/Compiler/CompilerService.cs @@ -150,7 +150,7 @@ public IEnumerable IdentifyElements(string source) // ToDo: The logic for determining if we should generate QIR should live in the SubmitterFactory as a // static function, `TargetSupportsQir`. We should then be calling that static function here for // PrepareQirGeneration instead of this logic. - // GitHub Issue: + // GitHub Issue: https://github.com/microsoft/qsharp-runtime/issues/968 PrepareQirGeneration = executionTarget?.StartsWith("microsoft.simulator") ?? false }; var loaded = new CompilationLoader(_ => sources, _ => references, loadOptions, logger); From 25d1fb671e774b8d7af68ea3718d315921d29808 Mon Sep 17 00:00:00 2001 From: Scott Carda Date: Fri, 18 Mar 2022 11:04:36 -0700 Subject: [PATCH 48/51] Undo PackageName --- src/AzureClient/AzureExecutionTarget.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/AzureClient/AzureExecutionTarget.cs b/src/AzureClient/AzureExecutionTarget.cs index 9738231a5e..1fdf1ed57f 100644 --- a/src/AzureClient/AzureExecutionTarget.cs +++ b/src/AzureClient/AzureExecutionTarget.cs @@ -21,7 +21,10 @@ protected AzureExecutionTarget(string? targetId) public string? TargetId { get; } - public virtual string PackageName => $"Microsoft.Quantum.Providers.{GetProvider(TargetId)}"; + public virtual string PackageName => + GetProvider(TargetId) == AzureProvider.Microsoft + ? "Microsoft.Quantum.Providers.Core" + : $"Microsoft.Quantum.Providers.{GetProvider(TargetId)}"; public RuntimeCapability RuntimeCapability => GetProvider(TargetId) switch { From 36f3ef0ee41159f2c729bca5a4eb1a054e4eef32 Mon Sep 17 00:00:00 2001 From: Scott Carda Date: Mon, 21 Mar 2022 11:11:01 -0700 Subject: [PATCH 49/51] Added comments to Where clause. --- src/AzureClient/AzureClient.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/AzureClient/AzureClient.cs b/src/AzureClient/AzureClient.cs index 2ea9e406d1..23639a1a0c 100644 --- a/src/AzureClient/AzureClient.cs +++ b/src/AzureClient/AzureClient.cs @@ -46,7 +46,9 @@ public class AzureClient : IAzureClient private IEnumerable? AvailableTargets => AvailableProviders ?.SelectMany(provider => provider.Targets) - ?.Where(t => t.TargetId != null && (t.TargetId.StartsWith(MicrosoftSimulator) || AzureExecutionTarget.GetProvider(t.TargetId) != AzureProvider.Microsoft)); + ?.Where(t => t.TargetId != null + && (t.TargetId.StartsWith(MicrosoftSimulator) // Of the Microsoft targets, we only want those that start with 'microsoft.simulator'. + || AzureExecutionTarget.GetProvider(t.TargetId) != AzureProvider.Microsoft)); // We want all non-Microsoft targets. private IEnumerable? ValidExecutionTargets => AvailableTargets?.Where(AzureExecutionTarget.IsValid); private string ValidExecutionTargetsDisplayText => (ValidExecutionTargets == null || ValidExecutionTargets.Count() == 0) From 22b5d596a5d98bcf14868ee07d21775640d5e050 Mon Sep 17 00:00:00 2001 From: Scott Carda Date: Mon, 21 Mar 2022 12:30:03 -0700 Subject: [PATCH 50/51] WIP IsQuantumExecutionTarget --- src/AzureClient/AzureClient.cs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/AzureClient/AzureClient.cs b/src/AzureClient/AzureClient.cs index 23639a1a0c..6de8ceebd0 100644 --- a/src/AzureClient/AzureClient.cs +++ b/src/AzureClient/AzureClient.cs @@ -28,7 +28,15 @@ namespace Microsoft.Quantum.IQSharp.AzureClient /// public class AzureClient : IAzureClient { - private const string MicrosoftSimulator = "microsoft.simulator"; + /// + /// Returns whether a target ID is meant for quantum execution since not all targets + /// exposed by providers are meant for that. More specifically, the Microsoft provider exposes + /// targets that are not meant for quantum execution and the only ones meant for that start + /// with "microsoft.simulator" + /// + private static bool IsQuantumExecutionTarget(string targetId) => + AzureExecutionTarget.GetProvider(targetId) != AzureProvider.Microsoft + || targetId.StartsWith("microsoft.simulator"); /// public Microsoft.Azure.Quantum.IWorkspace? ActiveWorkspace { get; private set; } @@ -43,12 +51,10 @@ public class AzureClient : IAzureClient private AzureExecutionTarget? ActiveTarget { get; set; } private string MostRecentJobId { get; set; } = string.Empty; private IEnumerable? AvailableProviders { get; set; } - private IEnumerable? AvailableTargets => + private IEnumerable? AvailableTargets => AvailableProviders ?.SelectMany(provider => provider.Targets) - ?.Where(t => t.TargetId != null - && (t.TargetId.StartsWith(MicrosoftSimulator) // Of the Microsoft targets, we only want those that start with 'microsoft.simulator'. - || AzureExecutionTarget.GetProvider(t.TargetId) != AzureProvider.Microsoft)); // We want all non-Microsoft targets. + ?.Where(t => t.TargetId != null && IsQuantumExecutionTarget(t.TargetId)); private IEnumerable? ValidExecutionTargets => AvailableTargets?.Where(AzureExecutionTarget.IsValid); private string ValidExecutionTargetsDisplayText => (ValidExecutionTargets == null || ValidExecutionTargets.Count() == 0) From d37146d0d399084130003be78a3fa1ff5fb14b1d Mon Sep 17 00:00:00 2001 From: Scott Carda Date: Mon, 21 Mar 2022 12:36:03 -0700 Subject: [PATCH 51/51] Added the MicrosoftSimulator const string back in. --- src/AzureClient/AzureClient.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/AzureClient/AzureClient.cs b/src/AzureClient/AzureClient.cs index 6de8ceebd0..adad8c4c13 100644 --- a/src/AzureClient/AzureClient.cs +++ b/src/AzureClient/AzureClient.cs @@ -28,6 +28,8 @@ namespace Microsoft.Quantum.IQSharp.AzureClient /// public class AzureClient : IAzureClient { + private const string MicrosoftSimulator = "microsoft.simulator"; + /// /// Returns whether a target ID is meant for quantum execution since not all targets /// exposed by providers are meant for that. More specifically, the Microsoft provider exposes @@ -36,7 +38,7 @@ public class AzureClient : IAzureClient /// private static bool IsQuantumExecutionTarget(string targetId) => AzureExecutionTarget.GetProvider(targetId) != AzureProvider.Microsoft - || targetId.StartsWith("microsoft.simulator"); + || targetId.StartsWith(MicrosoftSimulator); /// public Microsoft.Azure.Quantum.IWorkspace? ActiveWorkspace { get; private set; }