diff --git a/.gitignore b/.gitignore index 754c9b65976..354f05b9d0d 100644 --- a/.gitignore +++ b/.gitignore @@ -336,3 +336,4 @@ ASALocalRun/ # MFractors (Xamarin productivity tool) working folder .mfractor/ /src/Simulation/Simulators.Tests/TestProjects/QsharpExe/built +/src/Simulation/Simulators.Tests/TestProjects/TargetedExe/built diff --git a/Simulation.sln b/Simulation.sln index b22a08046ff..045a3b2c1dc 100644 --- a/Simulation.sln +++ b/Simulation.sln @@ -63,6 +63,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IonQExe", "src\Simulation\S EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "QCIExe", "src\Simulation\Simulators.Tests\TestProjects\QCIExe\QCIExe.csproj", "{C015FF41-9A51-4AF0-AEFC-2547D596B10A}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TargetedExe", "src\Simulation\Simulators.Tests\TestProjects\TargetedExe\TargetedExe.csproj", "{D292BF18-3956-4827-820E-254C3F81EF09}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -459,6 +461,22 @@ Global {C015FF41-9A51-4AF0-AEFC-2547D596B10A}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU {C015FF41-9A51-4AF0-AEFC-2547D596B10A}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU {C015FF41-9A51-4AF0-AEFC-2547D596B10A}.RelWithDebInfo|x64.Build.0 = Release|Any CPU + {D292BF18-3956-4827-820E-254C3F81EF09}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D292BF18-3956-4827-820E-254C3F81EF09}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D292BF18-3956-4827-820E-254C3F81EF09}.Debug|x64.ActiveCfg = Debug|Any CPU + {D292BF18-3956-4827-820E-254C3F81EF09}.Debug|x64.Build.0 = Debug|Any CPU + {D292BF18-3956-4827-820E-254C3F81EF09}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU + {D292BF18-3956-4827-820E-254C3F81EF09}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU + {D292BF18-3956-4827-820E-254C3F81EF09}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU + {D292BF18-3956-4827-820E-254C3F81EF09}.MinSizeRel|x64.Build.0 = Debug|Any CPU + {D292BF18-3956-4827-820E-254C3F81EF09}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D292BF18-3956-4827-820E-254C3F81EF09}.Release|Any CPU.Build.0 = Release|Any CPU + {D292BF18-3956-4827-820E-254C3F81EF09}.Release|x64.ActiveCfg = Release|Any CPU + {D292BF18-3956-4827-820E-254C3F81EF09}.Release|x64.Build.0 = Release|Any CPU + {D292BF18-3956-4827-820E-254C3F81EF09}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU + {D292BF18-3956-4827-820E-254C3F81EF09}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU + {D292BF18-3956-4827-820E-254C3F81EF09}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU + {D292BF18-3956-4827-820E-254C3F81EF09}.RelWithDebInfo|x64.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -489,6 +507,7 @@ Global {1448512E-132F-4DA8-BCBA-D98F16B31600} = {09C842CB-930C-4C7D-AD5F-E30DE4A55820} {55833C6C-6E91-4413-9F77-96B3A09666B8} = {09C842CB-930C-4C7D-AD5F-E30DE4A55820} {C015FF41-9A51-4AF0-AEFC-2547D596B10A} = {09C842CB-930C-4C7D-AD5F-E30DE4A55820} + {D292BF18-3956-4827-820E-254C3F81EF09} = {09C842CB-930C-4C7D-AD5F-E30DE4A55820} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {929C0464-86D8-4F70-8835-0A5EAF930821} diff --git a/bootstrap.cmd b/bootstrap.cmd index bceffe8091f..a7b49e63c01 100644 --- a/bootstrap.cmd +++ b/bootstrap.cmd @@ -12,9 +12,6 @@ git --version || GOTO missingGit :: Initialize C++ runtime project CALL :runtimeBootstrap || EXIT /B 1 -:: Initialize the compiler's nuspec file -CALL :nuspecBootstrap || EXIT /B 1 - :: Next steps are only needed for developers environment, they are skipped for cloud builds. IF NOT "%AGENT_ID%" == "" GOTO EOF @@ -33,17 +30,6 @@ popd EXIT /B -:: Bootstrap the compiler nuspec -:nuspecBootstrap -pushd src\Simulation\CsharpGeneration -CALL powershell -NoProfile .\FindNuspecReferences.ps1 || EXIT /B 1 -popd - -pushd src\Simulation\Simulators -CALL powershell -NoProfile .\FindNuspecReferences.ps1 || EXIT /B 1 -popd -EXIT /B - :missingGit echo. echo This script depends on git. diff --git a/bootstrap.ps1 b/bootstrap.ps1 new file mode 100644 index 00000000000..861a83f3f34 --- /dev/null +++ b/bootstrap.ps1 @@ -0,0 +1,24 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +$ErrorActionPreference = 'Stop' + +Push-Location (Join-Path $PSScriptRoot "src/Simulation/CsharpGeneration") + .\FindNuspecReferences.ps1 +Pop-Location + +Push-Location (Join-Path $PSScriptRoot "src/Simulation/Simulators") + .\FindNuspecReferences.ps1 +Pop-Location + +# bootstrap native folder +if ($Env:ENABLE_NATIVE -ne "false") { + ## Run the right script based on the OS. + if (-not (Test-Path Env:AGENT_OS) -or ($Env:AGENT_OS.StartsWith("Win"))) { + .\bootstrap.cmd + } else { + .\bootstrap.sh + } +} else { + Write-Host "Skipping native. ENABLE_NATIVE variable set to: $Env:ENABLE_NATIVE." +} \ No newline at end of file diff --git a/build/build.ps1 b/build/build.ps1 index 524c0895aa8..73bfd351d01 100644 --- a/build/build.ps1 +++ b/build/build.ps1 @@ -6,14 +6,18 @@ $ErrorActionPreference = 'Stop' & "$PSScriptRoot/set-env.ps1" $all_ok = $True -Write-Host "##[info]Build Native simulator" -cmake --build (Join-Path $PSScriptRoot "../src/Simulation/Native/build") --config $Env:BUILD_CONFIGURATION -if ($LastExitCode -ne 0) { - Write-Host "##vso[task.logissue type=error;]Failed to build Native simulator." - $script:all_ok = $False +if ($Env:ENABLE_NATIVE -ne "false") { + Write-Host "##[info]Build Native simulator" + $nativeBuild = (Join-Path $PSScriptRoot "../src/Simulation/Native/build") + cmake --build $nativeBuild --config $Env:BUILD_CONFIGURATION + if ($LastExitCode -ne 0) { + Write-Host "##vso[task.logissue type=error;]Failed to build Native simulator." + $script:all_ok = $False + } +} else { + Write-Host "Skipping native. ENABLE_NATIVE variable set to: $Env:ENABLE_NATIVE." } - function Build-One { param( [string]$action, diff --git a/build/ci.yml b/build/ci.yml index dc1942468d3..b274f861d26 100644 --- a/build/ci.yml +++ b/build/ci.yml @@ -9,34 +9,22 @@ variables: Drop.Native: $(System.DefaultWorkingDirectory)/xplat jobs: -- job: macOS - pool: - vmImage: 'macOS-latest' - steps: - - template: steps-xplat.yml - +- job: build + displayName: Build + strategy: + matrix: + linux: + imageName: 'ubuntu-latest' + mac: + imageName: 'macOS-latest' + windows: + imageName: 'windows-latest' + pool: + vmImage: $(imageName) -- job: Linux - pool: - vmImage: 'ubuntu-latest' steps: - - template: steps-xplat.yml - - -- job: Windows - pool: - vmImage: 'windows-2019' - dependsOn: - - macOS - - Linux - condition: succeeded() - steps: - - task: DownloadBuildArtifacts@0 - displayName: 'Download xplat native binaries' - inputs: - artifactName: xplat - downloadPath: $(System.DefaultWorkingDirectory) - template: steps.yml + - task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 displayName: 'Component Detection' inputs: diff --git a/build/manifest.ps1 b/build/manifest.ps1 index 29ea070beb7..147f234a98c 100644 --- a/build/manifest.ps1 +++ b/build/manifest.ps1 @@ -16,15 +16,15 @@ ); Assemblies = @( ".\src\Azure\Azure.Quantum.Client\bin\$Env:BUILD_CONFIGURATION\netstandard2.1\Microsoft.Azure.Quantum.Client.dll", - ".\src\simulation\CsharpGeneration\bin\$Env:BUILD_CONFIGURATION\netstandard2.1\Microsoft.Quantum.CsharpGeneration.dll", - ".\src\simulation\CsharpGeneration.App\bin\$Env:BUILD_CONFIGURATION\netcoreapp3.1\Microsoft.Quantum.CsharpGeneration.App.dll", - ".\src\simulation\CsharpGeneration.App\bin\$Env:BUILD_CONFIGURATION\netcoreapp3.1\Microsoft.Quantum.RoslynWrapper.dll", - ".\src\simulation\Core\bin\$Env:BUILD_CONFIGURATION\netstandard2.1\Microsoft.Quantum.Runtime.Core.dll", - ".\src\simulation\EntryPointDriver\bin\$Env:BUILD_CONFIGURATION\netstandard2.1\Microsoft.Quantum.EntryPointDriver.dll", - ".\src\simulation\QsharpCore\bin\$Env:BUILD_CONFIGURATION\netstandard2.1\Microsoft.Quantum.QSharp.Core.dll", - ".\src\simulation\Simulators\bin\$Env:BUILD_CONFIGURATION\netstandard2.1\Microsoft.Quantum.Simulation.Common.dll", - ".\src\simulation\Simulators\bin\$Env:BUILD_CONFIGURATION\netstandard2.1\Microsoft.Quantum.Simulation.QCTraceSimulatorRuntime.dll", - ".\src\simulation\Simulators\bin\$Env:BUILD_CONFIGURATION\netstandard2.1\Microsoft.Quantum.Simulators.dll", + ".\src\Simulation\CsharpGeneration\bin\$Env:BUILD_CONFIGURATION\netstandard2.1\Microsoft.Quantum.CsharpGeneration.dll", + ".\src\Simulation\CsharpGeneration.App\bin\$Env:BUILD_CONFIGURATION\netcoreapp3.1\Microsoft.Quantum.CsharpGeneration.App.dll", + ".\src\Simulation\CsharpGeneration.App\bin\$Env:BUILD_CONFIGURATION\netcoreapp3.1\Microsoft.Quantum.RoslynWrapper.dll", + ".\src\Simulation\Core\bin\$Env:BUILD_CONFIGURATION\netstandard2.1\Microsoft.Quantum.Runtime.Core.dll", + ".\src\Simulation\EntryPointDriver\bin\$Env:BUILD_CONFIGURATION\netstandard2.1\Microsoft.Quantum.EntryPointDriver.dll", + ".\src\Simulation\QsharpCore\bin\$Env:BUILD_CONFIGURATION\netstandard2.1\Microsoft.Quantum.QSharp.Core.dll", + ".\src\Simulation\Simulators\bin\$Env:BUILD_CONFIGURATION\netstandard2.1\Microsoft.Quantum.Simulation.Common.dll", + ".\src\Simulation\Simulators\bin\$Env:BUILD_CONFIGURATION\netstandard2.1\Microsoft.Quantum.Simulation.QCTraceSimulatorRuntime.dll", + ".\src\Simulation\Simulators\bin\$Env:BUILD_CONFIGURATION\netstandard2.1\Microsoft.Quantum.Simulators.dll", ".\src\Xunit\bin\$Env:BUILD_CONFIGURATION\netstandard2.1\Microsoft.Quantum.Xunit.dll" ) | ForEach-Object { Get-Item (Join-Path $PSScriptRoot (Join-Path ".." $_)) }; } | Write-Output; diff --git a/build/steps-init.yml b/build/steps-init.yml index 6c5d681bae7..694ba89302a 100644 --- a/build/steps-init.yml +++ b/build/steps-init.yml @@ -18,8 +18,6 @@ steps: ## # Bootstrap ## -- task: BatchScript@1 - displayName: 'Prepare build' - inputs: - filename: bootstrap.cmd - modifyEnvironment: true +- pwsh: ./bootstrap.ps1 + displayName: "Bootstrap repository" + workingDirectory: $(System.DefaultWorkingDirectory) diff --git a/build/steps-wrap-up.yml b/build/steps-wrap-up.yml index fb36f7194b8..9cf3a9957fc 100644 --- a/build/steps-wrap-up.yml +++ b/build/steps-wrap-up.yml @@ -12,7 +12,8 @@ steps: testRunTitle: 'Q# runtime tests' - task: PublishSymbols@1 - displayName: 'Publish symbols' + displayName: 'Publish symbols (Windows only)' + condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT')) continueOnError: true inputs: SearchPattern: '$(System.DefaultWorkingDirectory)/src/**/*.pdb' diff --git a/build/steps-xplat.yml b/build/steps-xplat.yml deleted file mode 100644 index 0af6e6d1300..00000000000 --- a/build/steps-xplat.yml +++ /dev/null @@ -1,50 +0,0 @@ -## -# xplat Native Simulator build -## -steps: - -- task: UseDotNet@2 - displayName: 'Use .NET Core SDK 3.1.100' - inputs: - packageType: sdk - version: '3.1.100' - - -- bash: ./bootstrap.sh - displayName: "Bootstrap repository" - workingDirectory: $(System.DefaultWorkingDirectory) - - -- powershell: ./build.ps1 - displayName: "Building Q# runtime" - workingDirectory: $(System.DefaultWorkingDirectory)/build - - -- powershell: ./test.ps1 - displayName: "Testing Q# runtime" - workingDirectory: $(System.DefaultWorkingDirectory)/build - condition: and(succeeded(), ne(variables['Skip.Tests'], 'true')) - - -- task: CopyFiles@2 - displayName: 'Copy Files to: artifact staging directory' - inputs: - SourceFolder: '$(System.DefaultWorkingDirectory)' - Contents: 'src/Simulation/Native/build/**' - TargetFolder: '$(Build.ArtifactStagingDirectory)' - - -- task: PublishTestResults@2 - displayName: 'Publish tests results' - condition: succeededOrFailed() - inputs: - testResultsFormat: VSTest - testResultsFiles: '$(System.DefaultWorkingDirectory)/**/*.trx' - testRunTitle: 'Q# xplat runtime tests' - - -- task: PublishBuildArtifacts@1 - displayName: 'Publish Artifact: xplat' - inputs: - PathtoPublish: '$(Build.ArtifactStagingDirectory)' - artifactName: xplat diff --git a/build/steps.yml b/build/steps.yml index 3b45dddd9eb..87da999f9e3 100644 --- a/build/steps.yml +++ b/build/steps.yml @@ -23,7 +23,8 @@ steps: - powershell: ./pack.ps1 - displayName: "Pack Q# runtime" + displayName: "Pack Q# runtime (Windows only)" + condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT')) workingDirectory: $(System.DefaultWorkingDirectory)/build diff --git a/build/test.ps1 b/build/test.ps1 index f66c42e0ad1..09e0e49fb9f 100644 --- a/build/test.ps1 +++ b/build/test.ps1 @@ -4,16 +4,19 @@ & "$PSScriptRoot/set-env.ps1" $all_ok = $True -Write-Host "##[info]Test Native simulator" -pushd (Join-Path $PSScriptRoot "../src/Simulation/Native/build") -cmake --build . --config $Env:BUILD_CONFIGURATION -ctest -C $Env:BUILD_CONFIGURATION -if ($LastExitCode -ne 0) { - Write-Host "##vso[task.logissue type=error;]Failed to test Native Simulator" - $script:all_ok = $False +if ($Env:ENABLE_NATIVE -ne "false") { + Write-Host "##[info]Test Native simulator" + pushd (Join-Path $PSScriptRoot "../src/Simulation/Native/build") + cmake --build . --config $Env:BUILD_CONFIGURATION + ctest -C $Env:BUILD_CONFIGURATION + if ($LastExitCode -ne 0) { + Write-Host "##vso[task.logissue type=error;]Failed to test Native Simulator" + $script:all_ok = $False + } + popd +} else { + Write-Host "Skipping native. ENABLE_NATIVE variable set to: $Env:ENABLE_NATIVE." } -popd - function Test-One { Param($project) diff --git a/src/Simulation/Common/QubitManager.cs b/src/Simulation/Common/QubitManager.cs index bd19bdad338..9bc54dfce3d 100644 --- a/src/Simulation/Common/QubitManager.cs +++ b/src/Simulation/Common/QubitManager.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using Microsoft.Quantum.Intrinsic; using Microsoft.Quantum.Simulation.Core; using Microsoft.Quantum.Simulation.Simulators.Exceptions; @@ -25,11 +26,13 @@ public class QubitManager long AllocatedForBorrowing; // All qubits allocated only for borrowing, will be marked with this number or higher. long[] qubits; // Tracks the allocation state of all qubits. long free; // Points to the first free (unallocated) qubit. + long freeTail; // Points to the last free (unallocated) qubit. Only valid iff (!EncourageReuse). long numAllocatedQubits; // Tracking this for optimization. long numDisabledQubits; // Number of disabled qubits. // Options bool MayExtendCapacity; + bool EncourageReuse; public bool DisableBorrowing { get; } const long MaxQubitCapacity = long.MaxValue - 3; @@ -49,9 +52,14 @@ public class QubitManager /// /// Creates and initializes QubitManager that can handle up to numQubits qubits /// - public QubitManager(long qubitCapacity, bool mayExtendCapacity = false, bool disableBorrowing = false) + public QubitManager( + long qubitCapacity, + bool mayExtendCapacity = false, + bool disableBorrowing = false, + bool encourageReuse = true) { MayExtendCapacity = mayExtendCapacity; + EncourageReuse = encourageReuse; DisableBorrowing = disableBorrowing; if (qubitCapacity <= 0) { qubitCapacity = MinQubitCapacity; } @@ -65,6 +73,7 @@ public QubitManager(long qubitCapacity, bool mayExtendCapacity = false, bool dis Debug.Assert(this.qubits[NumQubits - 1] == None); free = 0; + freeTail = NumQubits - 1; numAllocatedQubits = 0; numDisabledQubits = 0; } @@ -95,7 +104,6 @@ private void ExtendQubitArray() { if (oldQubitsArray[i] == oldNone) { // Point to the first new (free) element - Debug.Assert(false,"Why do we extend an array, when we still have available slots?"); this.qubits[i] = oldNumQubits; } else if (oldQubitsArray[i] == oldAllocated) { // Allocated qubits are marked differently now. @@ -121,9 +129,7 @@ private void ExtendQubitArray() if (free == oldNone) { free = oldNumQubits; - } else - { - Debug.Assert(false, "Why do we extend an array, when we still have available slots?"); + freeTail = NumQubits - 1; } } @@ -300,8 +306,29 @@ protected virtual void ReleaseOneQubit(Qubit qubit, bool usedOnlyForBorrowing) { throw new ArgumentException("Attempt to free qubit that has not been allocated."); } - qubits[qubit.Id] = free; - free = qubit.Id; + if (EncourageReuse) { + qubits[qubit.Id] = free; + free = qubit.Id; + } + else + { + // If we are allowed to extend capacity we will never reuse this qubit, + // otherwise we need to add it to the free qubits list. + if (!MayExtendCapacity) + { + if (qubits[freeTail] != None) + { + // There were no free qubits at all + free = qubit.Id; + } + else + { + qubits[freeTail] = qubit.Id; + } + } + qubits[qubit.Id] = None; + freeTail = qubit.Id; + } numAllocatedQubits--; Debug.Assert(numAllocatedQubits >= 0); diff --git a/src/Simulation/Common/QubitManagerTrackingScope.cs b/src/Simulation/Common/QubitManagerTrackingScope.cs index 23f654439de..a166f98bfa0 100644 --- a/src/Simulation/Common/QubitManagerTrackingScope.cs +++ b/src/Simulation/Common/QubitManagerTrackingScope.cs @@ -44,8 +44,12 @@ public List Locals private Stack operationStack; // Stack of operation calls. private StackFrame curFrame; // Current stack frame - all qubits in current scope are listed here. - public QubitManagerTrackingScope(long qubitCapacity, bool mayExtendCapacity = false, bool disableBorrowing = false) - : base(qubitCapacity, mayExtendCapacity, disableBorrowing) + public QubitManagerTrackingScope( + long qubitCapacity, + bool mayExtendCapacity = false, + bool disableBorrowing = false, + bool encourageReuse = true) + : base(qubitCapacity, mayExtendCapacity, disableBorrowing, encourageReuse) { if (!DisableBorrowing) { diff --git a/src/Simulation/Common/SimulatorBase.cs b/src/Simulation/Common/SimulatorBase.cs index 41f566ea641..7d216c00edf 100644 --- a/src/Simulation/Common/SimulatorBase.cs +++ b/src/Simulation/Common/SimulatorBase.cs @@ -196,7 +196,10 @@ public void EnableExceptionPrinting() /// no guarantee is made as to any particular action taken as a result /// of calling this method. /// - protected void MaybeDisplayDiagnostic(object data) + /// + /// The diagnostic object to be displayed. + /// + public void MaybeDisplayDiagnostic(object data) { OnDisplayableDiagnostic?.Invoke(data); } diff --git a/src/Simulation/Common/Simulators.Dev.props b/src/Simulation/Common/Simulators.Dev.props index 2c93b5ab65e..7c44b437a38 100644 --- a/src/Simulation/Common/Simulators.Dev.props +++ b/src/Simulation/Common/Simulators.Dev.props @@ -5,14 +5,17 @@ bin\$(BuildConfiguration)\$(TargetFramework)\$(AssemblyName).xml $([MSBuild]::NormalizeDirectory($(MSBuildThisFileDirectory)..\..\..\)) $([MSBuild]::NormalizePath($(EnlistmentRoot)src/Simulation/Native/build/)) + + + $([MSBuild]::NormalizePath($(NativeBuildPath)/libMicrosoft.Quantum.Simulator.Runtime.dylib)) $([MSBuild]::NormalizePath($(NativeBuildPath)/libMicrosoft.Quantum.Simulator.Runtime.so)) $([MSBuild]::NormalizePath($(NativeBuildPath)/Release/Microsoft.Quantum.Simulator.Runtime.dll)) $([MSBuild]::NormalizePath($(NativeBuildPath)/Debug/Microsoft.Quantum.Simulator.Runtime.dll)) - $(QsimDllMac) - $(QsimDllLinux) - $(QsimDllWindowsRelease) - $(QsimDllWindowsDebug) + $(QsimDllMac) + $(QsimDllLinux) + $(QsimDllWindowsRelease) + $(QsimDllWindowsDebug) @@ -23,6 +26,14 @@ + + + Microsoft.Quantum.Simulator.Runtime.dll + PreserveNewest + false + + + diff --git a/src/Simulation/Core/Operations/Operation.cs b/src/Simulation/Core/Operations/Operation.cs index aba000d7765..6a20d69af6c 100644 --- a/src/Simulation/Core/Operations/Operation.cs +++ b/src/Simulation/Core/Operations/Operation.cs @@ -16,7 +16,7 @@ public partial interface ICallable : ICallable { O Apply(I args); - ICallable Partial

(Func mapper); + ICallable Partial

(Func mapper); } ///

@@ -34,7 +34,7 @@ public interface IOperationWrapper /// /// Type of input parameters. /// Type of return values. - [DebuggerTypeProxy(typeof(Operation<,>.DebuggerProxy))] + [DebuggerTypeProxy(typeof(Operation<,>.DebuggerProxy))] public abstract class Operation : AbstractCallable, ICallable { private Lazy> _adjoint; @@ -56,7 +56,7 @@ public Operation(IOperationFactory m) : base(m) public virtual IApplyData __dataIn(I data) => new QTuple(data); - + public virtual IApplyData __dataOut(O data) => new QTuple(data); [DebuggerBrowsable(DebuggerBrowsableState.Never)] @@ -83,7 +83,7 @@ public Operation(IOperationFactory m) : base(m) { Label = ((ICallable)this).Name, FormattedNonQubitArgs = args.GetNonQubitArgumentsAsString() ?? "", - Targets = args.GetQubits() ?? new List(), + Targets = args.GetQubits()?.Distinct() ?? new List(), }; public O Apply(I a) @@ -95,7 +95,7 @@ public O Apply(I a) this.Factory?.StartOperation(this, __dataIn(a)); __result__ = this.Body(a); } - catch( Exception e) + catch (Exception e) { this.Factory?.Fail(System.Runtime.ExceptionServices.ExceptionDispatchInfo.Capture(e)); throw; @@ -105,7 +105,7 @@ public O Apply(I a) this.Factory?.EndOperation(this, __dataOut(__result__)); } - return __result__; + return __result__; } public T Partial(object partialInfo) @@ -212,7 +212,7 @@ internal class DebuggerProxy { private Operation op; - public DebuggerProxy(Operation op) + public DebuggerProxy(Operation op) { this.op = op; } diff --git a/src/Simulation/Core/TypeExtensions.cs b/src/Simulation/Core/TypeExtensions.cs index c47650b0b77..59cb0370b52 100644 --- a/src/Simulation/Core/TypeExtensions.cs +++ b/src/Simulation/Core/TypeExtensions.cs @@ -159,10 +159,16 @@ public static Type[] GetTupleFieldTypes(this Type arg) // If object is a Qubit, QVoid, or array of Qubits, ignore it (i.e. return null) if (o is Qubit || o is QVoid || o is IEnumerable) return null; + // If object is an ICallable, return its name + if (o is ICallable op) + { + return op.Name; + } + // If object is an IApplyData, recursively extract arguments if (o is IApplyData data) { - return data.Value.GetNonQubitArgumentsAsString(); + return data.Value?.GetNonQubitArgumentsAsString(); } // If object is a string, enclose it in quotations diff --git a/src/Simulation/CsharpGeneration.Tests/SimulationCodeTests.fs b/src/Simulation/CsharpGeneration.Tests/SimulationCodeTests.fs index de97e3aedc8..3c4cb093f9f 100644 --- a/src/Simulation/CsharpGeneration.Tests/SimulationCodeTests.fs +++ b/src/Simulation/CsharpGeneration.Tests/SimulationCodeTests.fs @@ -1242,7 +1242,7 @@ namespace N1 "X.Apply(qubits.Data[0L]);" "X.Adjoint.Apply(qubits.Data[0L]);" - "X.Controlled.Apply((qubits.Data?.Slice(new QRange(1L,5L)), qubits.Data[0L]));" + "X.Controlled.Apply((qubits.Data.Slice(new QRange(1L,5L)), qubits.Data[0L]));" "call_target1.Apply((1L, X, X, X, X));" "call_target1.Apply((1L, plain.Data, adj.Data, ctr.Data, uni.Data));" @@ -1820,7 +1820,7 @@ namespace N1 "var r5 = (IQArray)QArray.Create((4L + 2L));" "var r6 = QArray.Create(r5.Length);" "var r7 = (IQArray)QArray.Add(r2, r4);" - "var r8 = (IQArray)r7?.Slice(new QRange(1L, 5L, 10L));" + "var r8 = (IQArray)r7.Slice(new QRange(1L, 5L, 10L));" "var r9 = new arrays_T1(new QArray(Pauli.PauliX, Pauli.PauliY));" "var r10 = (IQArray)QArray.Create(4L);" @@ -1828,8 +1828,8 @@ namespace N1 "var r12 = (IQArray)QArray.Create(r10.Length);" "var r13 = new arrays_T3(new QArray>(new QArray(Result.Zero, Result.One), new QArray(Result.One, Result.Zero)));" "var r14 = (IQArray)QArray.Add(qubits, register.Data);" - "var r15 = (IQArray)register.Data?.Slice(new QRange(0L, 2L));" - "var r16 = (IQArray)qubits?.Slice(new QRange(1L, -(1L)));" + "var r15 = (IQArray)register.Data.Slice(new QRange(0L, 2L));" + "var r16 = (IQArray)qubits.Slice(new QRange(1L, -(1L)));" "var r18 = (IQArray)QArray.Create(2L);" "var r19 = (IQArray)QArray.Create(7L);" "var i0 = r13.Data[0L][1L];" @@ -1860,12 +1860,12 @@ namespace N1 "var r2 = new QRange(10L,-(2L),0L);" "var ranges = (IQArray)QArray.Create(1L);" - "var s1 = (IQArray)qubits?.Slice(new QRange(0L,10L));" - "var s2 = (IQArray)qubits?.Slice(r2);" - "var s3 = (IQArray)qubits?.Slice(ranges[3L]);" - "var s4 = (IQArray)qubits?.Slice(GetMeARange.Apply(QVoid.Instance));" + "var s1 = (IQArray)qubits.Slice(new QRange(0L,10L));" + "var s2 = (IQArray)qubits.Slice(r2);" + "var s3 = (IQArray)qubits.Slice(ranges[3L]);" + "var s4 = (IQArray)qubits.Slice(GetMeARange.Apply(QVoid.Instance));" - "return qubits?.Slice(new QRange(10L,-(3L),0L));" + "return qubits.Slice(new QRange(10L,-(3L),0L));" ] |> testOneBody (applyVisitor sliceOperations) @@ -2335,7 +2335,7 @@ namespace N1 let testOneClass (_,op : QsCallable) executionTarget (expected : string) = let expected = expected.Replace("%%%", HttpUtility.JavaScriptStringEncode op.SourceFile.Value) let assemblyConstants = - new System.Collections.Generic.KeyValuePair<_,_> (AssemblyConstants.ExecutionTarget, executionTarget) + new Collections.Generic.KeyValuePair<_,_> (AssemblyConstants.ProcessorArchitecture, executionTarget) |> Seq.singleton |> ImmutableDictionary.CreateRange let compilation = {Namespaces = syntaxTree; EntryPoints = ImmutableArray.Create op.FullName} @@ -3529,7 +3529,7 @@ namespace Microsoft.Quantum.Tests.LineNumbers else { #line 20 "%%" - foreach (var c in ctrls?.Slice(new QRange(0L, 2L, r))) + foreach (var c in ctrls.Slice(new QRange(0L, 2L, r))) #line hidden { #line 21 "%%" diff --git a/src/Simulation/CsharpGeneration/Context.fs b/src/Simulation/CsharpGeneration/Context.fs index 411ab9c5e9c..df74e8ea9e7 100644 --- a/src/Simulation/CsharpGeneration/Context.fs +++ b/src/Simulation/CsharpGeneration/Context.fs @@ -104,6 +104,11 @@ type CodegenContext = { static member public Create (syntaxTree : ImmutableArray) = CodegenContext.Create(syntaxTree, ImmutableDictionary.Empty) + member public this.ProcessorArchitecture = + match this.assemblyConstants.TryGetValue AssemblyConstants.ProcessorArchitecture with + | true, name -> name + | false, _ -> null + member public this.ExecutionTarget = match this.assemblyConstants.TryGetValue AssemblyConstants.ExecutionTarget with | true, name -> name @@ -116,7 +121,7 @@ type CodegenContext = { member internal this.GenerateCodeForSource (fileName : NonNullable) = let targetsQuantumProcessor = - match this.assemblyConstants.TryGetValue AssemblyConstants.ExecutionTarget with + match this.assemblyConstants.TryGetValue AssemblyConstants.ProcessorArchitecture with | true, target -> target = AssemblyConstants.HoneywellProcessor || target = AssemblyConstants.IonQProcessor || target = AssemblyConstants.QCIProcessor | _ -> false not (fileName.Value.EndsWith ".dll") || targetsQuantumProcessor diff --git a/src/Simulation/CsharpGeneration/FindNuspecReferences.ps1 b/src/Simulation/CsharpGeneration/FindNuspecReferences.ps1 index 0c3695812f9..f669dac1860 100644 --- a/src/Simulation/CsharpGeneration/FindNuspecReferences.ps1 +++ b/src/Simulation/CsharpGeneration/FindNuspecReferences.ps1 @@ -21,13 +21,13 @@ using namespace System.IO -$target = 'Microsoft.Quantum.CsharpGeneration.nuspec' +$target = Join-Path $PSScriptRoot 'Microsoft.Quantum.CsharpGeneration.nuspec' if (Test-Path $target) { Write-Host "$target exists. Skipping generating new one." exit } -$nuspec = [Xml](Get-Content 'Microsoft.Quantum.CsharpGeneration.nuspec.template') +$nuspec = [Xml](Get-Content (Join-Path $PSScriptRoot 'Microsoft.Quantum.CsharpGeneration.nuspec.template')) $dependencies = $nuspec.CreateElement('dependencies', $nuspec.package.metadata.NamespaceURI) # Adds a dependency to the dependencies element if it does not already exist. diff --git a/src/Simulation/CsharpGeneration/Microsoft.Quantum.CsharpGeneration.fsproj b/src/Simulation/CsharpGeneration/Microsoft.Quantum.CsharpGeneration.fsproj index 5f63b02f224..adb70f031db 100644 --- a/src/Simulation/CsharpGeneration/Microsoft.Quantum.CsharpGeneration.fsproj +++ b/src/Simulation/CsharpGeneration/Microsoft.Quantum.CsharpGeneration.fsproj @@ -21,7 +21,7 @@ - + diff --git a/src/Simulation/CsharpGeneration/SimulationCode.fs b/src/Simulation/CsharpGeneration/SimulationCode.fs index e7a30aa50e4..74b0e8428a2 100644 --- a/src/Simulation/CsharpGeneration/SimulationCode.fs +++ b/src/Simulation/CsharpGeneration/SimulationCode.fs @@ -561,7 +561,7 @@ module SimulationCode = and buildArrayItem a i = match i.ResolvedType.Resolution with - | Range -> ``invoke`` ((buildExpression a) <|?.|> (``ident`` "Slice")) ``(`` [ (buildExpression i) ] ``)`` + | Range -> ``invoke`` ((buildExpression a) <|.|> (``ident`` "Slice")) ``(`` [ (buildExpression i) ] ``)`` | _ -> ``item`` (buildExpression a) [ (buildExpression i) ] let buildBlock (block : QsScope) = @@ -927,7 +927,7 @@ module SimulationCode = /// Returns a static property of type OperationInfo using the operation's input and output types. let buildOperationInfoProperty (globalContext:CodegenContext) operationInput operationOutput operationName = let propertyType = - match globalContext.ExecutionTarget with + match globalContext.ProcessorArchitecture with | target when target = AssemblyConstants.HoneywellProcessor -> sprintf "HoneywellEntryPointInfo<%s, %s>" operationInput operationOutput | target when target = AssemblyConstants.IonQProcessor -> sprintf "IonQEntryPointInfo<%s, %s>" operationInput operationOutput | target when target = AssemblyConstants.QCIProcessor -> sprintf "QCIEntryPointInfo<%s, %s>" operationInput operationOutput diff --git a/src/Simulation/Native/bootstrap.cmd b/src/Simulation/Native/bootstrap.cmd index 144b1686a9f..cd32571ecd4 100644 --- a/src/Simulation/Native/bootstrap.cmd +++ b/src/Simulation/Native/bootstrap.cmd @@ -23,6 +23,10 @@ IF EXIST %DROP_FOLDER%\Release\Microsoft.Quantum.Simulator.Runtime.dll copy %DRO IF NOT EXIST %BUILD_FOLDER% mkdir %BUILD_FOLDER% pushd %BUILD_FOLDER% +IF NOT EXIST Release mkdir Release +IF EXIST %DROP_FOLDER%\Release\Microsoft.Quantum.Simulator.Runtime.dll copy %DROP_FOLDER%\Release\Microsoft.Quantum.Simulator.Runtime.dll Release\Microsoft.Quantum.Simulator.Runtime.dll + + cmake -A "x64" ^ -DBUILD_SHARED_LIBS:BOOL="1" ^ .. diff --git a/src/Simulation/Native/src/simulator/capi.cpp b/src/Simulation/Native/src/simulator/capi.cpp index 5f081acb159..344445f46c4 100644 --- a/src/Simulation/Native/src/simulator/capi.cpp +++ b/src/Simulation/Native/src/simulator/capi.cpp @@ -21,13 +21,13 @@ MICROSOFT_QUANTUM_DECL void destroy(_In_ unsigned id) MICROSOFT_QUANTUM_DECL void seed(_In_ unsigned id, _In_ unsigned s) { - psis[id]->seed(s); + Microsoft::Quantum::Simulator::get(id)->seed(s); } // non-quantum MICROSOFT_QUANTUM_DECL std::size_t random_choice(_In_ unsigned id, _In_ std::size_t n, _In_reads_(n) double* p) { - return psis[id]->random(n, p); + return Microsoft::Quantum::Simulator::get(id)->random(n, p); } MICROSOFT_QUANTUM_DECL double JointEnsembleProbability(_In_ unsigned id, _In_ unsigned n, _In_reads_(n) int* b, _In_reads_(n) unsigned* q) @@ -36,35 +36,35 @@ MICROSOFT_QUANTUM_DECL double JointEnsembleProbability(_In_ unsigned id, _In_ un for (unsigned i = 0; i < n; ++i) bv.push_back(static_cast(*(b + i))); std::vector qv(q, q + n); - return psis[id]->JointEnsembleProbability( bv, qv); + return Microsoft::Quantum::Simulator::get(id)->JointEnsembleProbability( bv, qv); } MICROSOFT_QUANTUM_DECL void allocateQubit(_In_ unsigned id, _In_ unsigned q) { - psis[id]->allocateQubit(q); + Microsoft::Quantum::Simulator::get(id)->allocateQubit(q); } MICROSOFT_QUANTUM_DECL void release(_In_ unsigned id, _In_ unsigned q) { - psis[id]->release(q); + Microsoft::Quantum::Simulator::get(id)->release(q); } MICROSOFT_QUANTUM_DECL unsigned num_qubits(_In_ unsigned id) { - return psis[id]->num_qubits(); + return Microsoft::Quantum::Simulator::get(id)->num_qubits(); } #define FWDGATE1(G) \ MICROSOFT_QUANTUM_DECL void G(_In_ unsigned id, _In_ unsigned q) \ { \ - psis[id]->G(q); \ + Microsoft::Quantum::Simulator::get(id)->G(q); \ } #define FWDCSGATE1(G) \ MICROSOFT_QUANTUM_DECL void MC##G(_In_ unsigned id, _In_ unsigned n, _In_reads_(n) unsigned* c, _In_ unsigned q) \ { \ std::vector vc(c, c + n); \ - psis[id]->C##G(vc, q); \ + Microsoft::Quantum::Simulator::get(id)->C##G(vc, q); \ } #define FWD(G) FWDGATE1(G) FWDCSGATE1(G) @@ -88,14 +88,14 @@ FWD(AdjT) MICROSOFT_QUANTUM_DECL void R(_In_ unsigned id, _In_ unsigned b, _In_ double phi, _In_ unsigned q) { - psis[id]->R(static_cast(b), phi, q); + Microsoft::Quantum::Simulator::get(id)->R(static_cast(b), phi, q); } // multi-controlled rotations MICROSOFT_QUANTUM_DECL void MCR(_In_ unsigned id, _In_ unsigned b, _In_ double phi, _In_ unsigned nc, _In_reads_(nc) unsigned* c, _In_ unsigned q) { std::vector cv(c, c + nc); - psis[id]->CR(static_cast(b), phi, cv, q); + Microsoft::Quantum::Simulator::get(id)->CR(static_cast(b), phi, cv, q); } // Exponential of Pauli operators @@ -105,7 +105,7 @@ MICROSOFT_QUANTUM_DECL void Exp(_In_ unsigned id, _In_ unsigned n, _In_reads_(n) for (unsigned i = 0; i < n; ++i) bv.push_back(static_cast(*(b + i))); std::vector qv(q, q + n); - psis[id]->Exp(bv, phi, qv); + Microsoft::Quantum::Simulator::get(id)->Exp(bv, phi, qv); } MICROSOFT_QUANTUM_DECL void MCExp(_In_ unsigned id, _In_ unsigned n, _In_reads_(n) unsigned* b, _In_ double phi, _In_ unsigned nc, _In_reads_(nc) unsigned* c, _In_reads_(n) unsigned* q) { @@ -114,13 +114,13 @@ MICROSOFT_QUANTUM_DECL void MCExp(_In_ unsigned id, _In_ unsigned n, _In_reads_( bv.push_back(static_cast(*(b + i))); std::vector qv(q, q + n); std::vector cv(c, c + nc); - psis[id]->CExp(bv, phi, cv, qv); + Microsoft::Quantum::Simulator::get(id)->CExp(bv, phi, cv, qv); } // measurements MICROSOFT_QUANTUM_DECL unsigned M(_In_ unsigned id, _In_ unsigned q) { - return (unsigned)psis[id]->M(q); + return (unsigned)Microsoft::Quantum::Simulator::get(id)->M(q); } MICROSOFT_QUANTUM_DECL unsigned Measure(_In_ unsigned id, _In_ unsigned n, _In_reads_(n) unsigned* b, _In_reads_(n) unsigned* q) { @@ -128,7 +128,7 @@ MICROSOFT_QUANTUM_DECL unsigned Measure(_In_ unsigned id, _In_ unsigned n, _In_r for (unsigned i = 0; i < n; ++i) bv.push_back(static_cast(*(b + i))); std::vector qv(q, q + n); - return (unsigned)psis[id]->Measure(bv, qv); + return (unsigned)Microsoft::Quantum::Simulator::get(id)->Measure(bv, qv); } // apply permutation of basis states to the wave function @@ -136,33 +136,33 @@ MICROSOFT_QUANTUM_DECL void PermuteBasis(_In_ unsigned id, _In_ unsigned n, _In_ _In_reads_(table_size) std::size_t *permutation_table) { const std::vector qs(q, q + n); - psis[id]->permuteBasis(qs, table_size, permutation_table, false); + Microsoft::Quantum::Simulator::get(id)->permuteBasis(qs, table_size, permutation_table, false); } MICROSOFT_QUANTUM_DECL void AdjPermuteBasis(_In_ unsigned id, _In_ unsigned n, _In_reads_(n) unsigned* q, _In_ std::size_t table_size, _In_reads_(table_size) std::size_t *permutation_table) { const std::vector qs(q, q + n); - psis[id]->permuteBasis(qs, table_size, permutation_table, true); + Microsoft::Quantum::Simulator::get(id)->permuteBasis(qs, table_size, permutation_table, true); } // dump wavefunction to given callback until callback returns false MICROSOFT_QUANTUM_DECL void Dump(_In_ unsigned id, _In_ bool (*callback)(size_t, double, double)) { - psis[id]->dump(callback); + Microsoft::Quantum::Simulator::get(id)->dump(callback); } // dump the wavefunction of the subset of qubits to the given callback returns false MICROSOFT_QUANTUM_DECL bool DumpQubits(_In_ unsigned id, _In_ unsigned n, _In_reads_(n) unsigned* q, _In_ bool(*callback)(size_t, double, double)) { std::vector qs(q, q + n); - return psis[id]->dumpQubits(qs, callback); + return Microsoft::Quantum::Simulator::get(id)->dumpQubits(qs, callback); } // dump the list of logical qubit ids to given callback MICROSOFT_QUANTUM_DECL void DumpIds(_In_ unsigned id, _In_ void(*callback)(unsigned)) { - psis[id]->dumpIds(callback); + Microsoft::Quantum::Simulator::get(id)->dumpIds(callback); } } diff --git a/src/Simulation/Native/src/simulator/capi_test.cpp b/src/Simulation/Native/src/simulator/capi_test.cpp index feb725db2fa..945127e260d 100644 --- a/src/Simulation/Native/src/simulator/capi_test.cpp +++ b/src/Simulation/Native/src/simulator/capi_test.cpp @@ -23,12 +23,12 @@ void CZ(unsigned sim_id, unsigned c, unsigned q) void Ry(unsigned sim_id, double phi, unsigned q) { - R(sim_id,2,phi,q); + R(sim_id,3,phi,q); } void CRz(unsigned sim_id, double phi, unsigned c, unsigned q) { - MCR(sim_id,3,phi,1,&c,q); + MCR(sim_id,2,phi,1,&c,q); } void CRx(unsigned sim_id, double phi, unsigned c, unsigned q) @@ -115,7 +115,7 @@ void test_gates() CRx(sim_id, 1.0, 0, 1); H(sim_id, 1); - CRx(sim_id, -1.0, 0, 1); + CRz(sim_id, -1.0, 0, 1); H(sim_id, 1); assert(M(sim_id, 1)==false); diff --git a/src/Simulation/Native/src/simulator/factory.cpp b/src/Simulation/Native/src/simulator/factory.cpp index 6d46fbcf7f7..b80b02b35f6 100644 --- a/src/Simulation/Native/src/simulator/factory.cpp +++ b/src/Simulation/Native/src/simulator/factory.cpp @@ -5,6 +5,7 @@ #include "config.hpp" #include "util/cpuid.hpp" #include +#include namespace Microsoft { @@ -31,7 +32,8 @@ namespace Microsoft { namespace Simulator { - mutex_type _mutex; + std::shared_mutex _mutex; + std::vector> _psis; SimulatorInterface* createSimulator(unsigned maxlocal) { @@ -52,26 +54,26 @@ namespace Microsoft MICROSOFT_QUANTUM_DECL unsigned create(unsigned maxlocal) { - std::lock_guard lock(_mutex); + std::lock_guard lock(_mutex); size_t emptySlot = -1; - for (auto const& s : psis) + for (auto const& s : _psis) { if (s == NULL) { - emptySlot = &s - &psis[0]; + emptySlot = &s - &_psis[0]; break; } } if (emptySlot == -1) { - psis.push_back(std::shared_ptr(createSimulator(maxlocal))); - emptySlot = psis.size() - 1; + _psis.push_back(std::shared_ptr(createSimulator(maxlocal))); + emptySlot = _psis.size() - 1; } else { - psis[emptySlot] = std::shared_ptr(createSimulator(maxlocal)); + _psis[emptySlot] = std::shared_ptr(createSimulator(maxlocal)); } return static_cast(emptySlot); @@ -79,12 +81,17 @@ namespace Microsoft MICROSOFT_QUANTUM_DECL void destroy(unsigned id) { - std::lock_guard lock(_mutex); + std::lock_guard lock(_mutex); - psis[id].reset(); + _psis[id].reset(); } - MICROSOFT_QUANTUM_DECL std::vector> psis; + MICROSOFT_QUANTUM_DECL std::shared_ptr& get(unsigned id) + { + std::shared_lock shared_lock(_mutex); + + return _psis[id]; + } } } diff --git a/src/Simulation/Native/src/simulator/factory.hpp b/src/Simulation/Native/src/simulator/factory.hpp index ec9d097fc8a..979b4a3b052 100644 --- a/src/Simulation/Native/src/simulator/factory.hpp +++ b/src/Simulation/Native/src/simulator/factory.hpp @@ -12,8 +12,7 @@ namespace Microsoft { MICROSOFT_QUANTUM_DECL unsigned create(unsigned =0u); MICROSOFT_QUANTUM_DECL void destroy(unsigned); - - extern MICROSOFT_QUANTUM_DECL std::vector> psis; + MICROSOFT_QUANTUM_DECL std::shared_ptr& get(unsigned); } } } diff --git a/src/Simulation/Native/src/simulator/factory_test.cpp b/src/Simulation/Native/src/simulator/factory_test.cpp index 6c196205713..d4745fa2d90 100644 --- a/src/Simulation/Native/src/simulator/factory_test.cpp +++ b/src/Simulation/Native/src/simulator/factory_test.cpp @@ -8,7 +8,7 @@ using namespace Microsoft::Quantum::Simulator; int main(int argc, char** argv) { - auto& sim = psis[create()]; + auto sim = get(create()); unsigned q=0; // qubit number sim->allocateQubit(q); diff --git a/src/Simulation/QCTraceSimulator.Tests/Tests.Microsoft.Quantum.Simulation.QCTraceSimulatorRuntime.csproj b/src/Simulation/QCTraceSimulator.Tests/Tests.Microsoft.Quantum.Simulation.QCTraceSimulatorRuntime.csproj index 92aab6749f8..c2f1c3086fd 100644 --- a/src/Simulation/QCTraceSimulator.Tests/Tests.Microsoft.Quantum.Simulation.QCTraceSimulatorRuntime.csproj +++ b/src/Simulation/QCTraceSimulator.Tests/Tests.Microsoft.Quantum.Simulation.QCTraceSimulatorRuntime.csproj @@ -1,4 +1,4 @@ - + diff --git a/src/Simulation/QsharpCore/Intrinsic.cs b/src/Simulation/QsharpCore/Intrinsic.cs index 76976a0f217..f7bbd4d953b 100644 --- a/src/Simulation/QsharpCore/Intrinsic.cs +++ b/src/Simulation/QsharpCore/Intrinsic.cs @@ -76,4 +76,16 @@ public partial class M return null; } } + + public partial class ResetAll + { + /// + public override RuntimeMetadata? GetRuntimeMetadata(IApplyData args) + { + var metadata = base.GetRuntimeMetadata(args); + if (metadata == null) throw new NullReferenceException($"Null RuntimeMetadata found for {this.ToString()}."); + metadata.IsComposite = true; + return metadata; + } + } } diff --git a/src/Simulation/QsharpCore/Microsoft.Quantum.QSharp.Core.csproj b/src/Simulation/QsharpCore/Microsoft.Quantum.QSharp.Core.csproj index ffe59c9eaec..58d1c0a798e 100644 --- a/src/Simulation/QsharpCore/Microsoft.Quantum.QSharp.Core.csproj +++ b/src/Simulation/QsharpCore/Microsoft.Quantum.QSharp.Core.csproj @@ -1,4 +1,4 @@ - + diff --git a/src/Simulation/Simulators.Tests/Circuits/Issue132.qs b/src/Simulation/Simulators.Tests/Circuits/Issue132.qs new file mode 100644 index 00000000000..9b57996913a --- /dev/null +++ b/src/Simulation/Simulators.Tests/Circuits/Issue132.qs @@ -0,0 +1,25 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Simulation.Simulators.Tests.Circuits +{ + open Microsoft.Quantum.Intrinsic; + + operation SliceGenerationTest() : Unit { + using (qs = Qubit[4]) { + PrepareCatState(qs); + if (M(qs[0]) == One) { + for (target in qs) { + X(target); + } + } + } + } + + operation PrepareCatState(register : Qubit[]) : Unit is Adj + Ctl { + H(register[0]); + for (target in register[1...]) { + CNOT(register[0], target); + } + } +} diff --git a/src/Simulation/Simulators.Tests/Circuits/RuntimeMetadataTest.qs b/src/Simulation/Simulators.Tests/Circuits/RuntimeMetadataTest.qs index 668f7ee5bf5..4e721723832 100644 --- a/src/Simulation/Simulators.Tests/Circuits/RuntimeMetadataTest.qs +++ b/src/Simulation/Simulators.Tests/Circuits/RuntimeMetadataTest.qs @@ -11,6 +11,11 @@ namespace Microsoft.Quantum.Simulation.Simulators.Tests.Circuits { operation Empty () : Unit is Ctl + Adj { } + operation WrapperOp (op: (Qubit => Unit), q : Qubit) : Unit { + op(q); + Reset(q); + } + operation HOp (q : Qubit) : Unit { H(q); Reset(q); @@ -21,5 +26,9 @@ namespace Microsoft.Quantum.Simulation.Simulators.Tests.Circuits { HOp(q); } } + + operation TwoQubitOp (q1 : Qubit, q2 : Qubit) : Unit { + // ... + } } diff --git a/src/Simulation/Simulators.Tests/CoreTests.cs b/src/Simulation/Simulators.Tests/CoreTests.cs index 185351df696..88917ff4c24 100644 --- a/src/Simulation/Simulators.Tests/CoreTests.cs +++ b/src/Simulation/Simulators.Tests/CoreTests.cs @@ -43,6 +43,20 @@ public void BasicExecution() Assert.Empty(error.ToString().Trim()); } + [Fact] + public void BasicExecutionTargetedExe() + { + var asmPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + var exe = Path.Combine(asmPath, "TestTargetedExe", "TargetedExe.dll"); + + ProcessRunner.Run("dotnet", exe, out StringBuilder output, out StringBuilder error, out int exitCode, out Exception ex); + + Assert.Null(ex); + Assert.Equal(0, exitCode); + Assert.Empty(error.ToString().Trim()); + Assert.Equal("TargetedExe", output.ToString().Trim()); + } + [Fact] public void Borrowing() { diff --git a/src/Simulation/Simulators.Tests/QubitManagerTests.cs b/src/Simulation/Simulators.Tests/QubitManagerTests.cs index a5f2123d0f2..8ee972883a8 100644 --- a/src/Simulation/Simulators.Tests/QubitManagerTests.cs +++ b/src/Simulation/Simulators.Tests/QubitManagerTests.cs @@ -152,6 +152,91 @@ public void TestQubitManager() } } + /// + /// Test for QubitManager. + /// + [Fact] + public void TestQubitManagerDiscouragingReuse() + { + { // BLOCK testing mayExtendCapacity:false + QubitManager qm = new QubitManager(10, mayExtendCapacity: false, disableBorrowing: false, encourageReuse: false); + + // Test allocation of single qubit + Qubit q1 = qm.Allocate(); + Assert.True(q1.Id == 0); + + // Test allocation of multiple qubits + IQArray qa1 = qm.Allocate(4); + Assert.True(qa1.Length == 4); + Assert.True(qa1[0].Id == 1); + Assert.True(qa1[1].Id == 2); + Assert.True(qa1[2].Id == 3); + Assert.True(qa1[3].Id == 4); + + // Test reuse of deallocated qubits + qm.Release(qa1[1]); + + Qubit q2 = qm.Allocate(); + Assert.True(q2.Id == 5); + + IQArray qa2 = qm.Allocate(3); + Assert.True(qa2.Length == 3); + Assert.True(qa2[0].Id == 6); + Assert.True(qa2[1].Id == 7); + Assert.True(qa2[2].Id == 8); + + qm.Release(qa2); + + Qubit q3 = qm.Allocate(); + Assert.True(q3.Id == 9); + + Qubit q4 = qm.Allocate(); + Assert.True(q4.Id == 2); + + Qubit q5 = qm.Allocate(); + Assert.True(q5.Id == 8); + } + + { // BLOCK testing mayExtendCapacity:true + QubitManager qm = new QubitManager(10, mayExtendCapacity: true, disableBorrowing: false, encourageReuse: false); + + // Test allocation of single qubit + Qubit q1 = qm.Allocate(); + Assert.True(q1.Id == 0); + + // Test allocation of multiple qubits + IQArray qa1 = qm.Allocate(4); + Assert.True(qa1.Length == 4); + Assert.True(qa1[0].Id == 1); + Assert.True(qa1[1].Id == 2); + Assert.True(qa1[2].Id == 3); + Assert.True(qa1[3].Id == 4); + + // Test reuse of deallocated qubits + qm.Release(qa1[1]); + + Qubit q2 = qm.Allocate(); + Assert.True(q2.Id == 5); + + IQArray qa2 = qm.Allocate(3); + Assert.True(qa2.Length == 3); + Assert.True(qa2[0].Id == 6); + Assert.True(qa2[1].Id == 7); + Assert.True(qa2[2].Id == 8); + + qm.Release(qa2); + + Qubit q3 = qm.Allocate(); + Assert.True(q3.Id == 9); + + Qubit q4 = qm.Allocate(); + Assert.True(q4.Id == 10); + + Qubit q5 = qm.Allocate(); + Assert.True(q5.Id == 11); + } + } + /// /// Test for QubitManagerTrackingScope. /// diff --git a/src/Simulation/Simulators.Tests/RuntimeMetadataTests.cs b/src/Simulation/Simulators.Tests/RuntimeMetadataTests.cs index 629417598b0..e9f6e69e626 100644 --- a/src/Simulation/Simulators.Tests/RuntimeMetadataTests.cs +++ b/src/Simulation/Simulators.Tests/RuntimeMetadataTests.cs @@ -297,6 +297,28 @@ public void M() Assert.Equal(op.GetRuntimeMetadata(args), expected); } + [Fact] + public void Reset() + { + var target = new FreeQubit(0); + var op = new QuantumSimulator().Get(); + var args = op.__dataIn(target); + var expected = new RuntimeMetadata() + { + Label = "Reset", + FormattedNonQubitArgs = "", + IsAdjoint = false, + IsControlled = false, + IsMeasurement = false, + IsComposite = false, + Children = null, + Controls = new List() { }, + Targets = new List() { target }, + }; + + Assert.Equal(op.GetRuntimeMetadata(args), expected); + } + [Fact] public void ResetAll() { @@ -310,7 +332,7 @@ public void ResetAll() IsAdjoint = false, IsControlled = false, IsMeasurement = false, - IsComposite = false, + IsComposite = true, Children = null, Controls = new List() { }, Targets = targets, @@ -387,7 +409,10 @@ public void MResetZ() Assert.Equal(op.GetRuntimeMetadata(args), expected); } + } + public class CustomCircuitTests + { [Fact] public void EmptyOperation() { @@ -410,10 +435,32 @@ public void EmptyOperation() Assert.Equal(op.GetRuntimeMetadata(args), expected); } + [Fact] + public void OperationAsArgument() + { + var q = new FreeQubit(0); + var opArg = new QuantumSimulator().Get(); + var op = new QuantumSimulator().Get(); + var args = op.__dataIn((opArg, q)); + var expected = new RuntimeMetadata() + { + Label = "WrapperOp", + FormattedNonQubitArgs = "(HOp)", + IsAdjoint = false, + IsControlled = false, + IsMeasurement = false, + IsComposite = false, + Children = null, + Controls = new List() { }, + Targets = new List() { q }, + }; + + Assert.Equal(op.GetRuntimeMetadata(args), expected); + } + [Fact] public void NestedOperation() { - var measureQubit = new FreeQubit(0); var op = new QuantumSimulator().Get(); var args = op.__dataIn(QVoid.Instance); var expected = new RuntimeMetadata() @@ -431,6 +478,28 @@ public void NestedOperation() Assert.Equal(op.GetRuntimeMetadata(args), expected); } + + [Fact] + public void DuplicateQubitArgs() + { + var q = new FreeQubit(0); + var op = new QuantumSimulator().Get(); + var args = op.__dataIn((q, q)); + var expected = new RuntimeMetadata() + { + Label = "TwoQubitOp", + FormattedNonQubitArgs = "", + IsAdjoint = false, + IsControlled = false, + IsMeasurement = false, + IsComposite = false, + Children = null, + Controls = new List() { }, + Targets = new List() { q }, + }; + + Assert.Equal(op.GetRuntimeMetadata(args), expected); + } } public class UDTTests diff --git a/src/Simulation/Simulators.Tests/TestProjects/HoneywellExe/HoneywellExe.csproj b/src/Simulation/Simulators.Tests/TestProjects/HoneywellExe/HoneywellExe.csproj index a8a9bf880bc..4e889590a38 100644 --- a/src/Simulation/Simulators.Tests/TestProjects/HoneywellExe/HoneywellExe.csproj +++ b/src/Simulation/Simulators.Tests/TestProjects/HoneywellExe/HoneywellExe.csproj @@ -1,4 +1,4 @@ - + Library diff --git a/src/Simulation/Simulators.Tests/TestProjects/IonQExe/IonQExe.csproj b/src/Simulation/Simulators.Tests/TestProjects/IonQExe/IonQExe.csproj index 50759c6ff87..7f122de74d7 100644 --- a/src/Simulation/Simulators.Tests/TestProjects/IonQExe/IonQExe.csproj +++ b/src/Simulation/Simulators.Tests/TestProjects/IonQExe/IonQExe.csproj @@ -1,25 +1,25 @@ - - - - Library - netcoreapp3.1 - - false - false - false - true - ionq.qpu - - - - - - - - - - - - - - + + + + Library + netcoreapp3.1 + + false + false + false + true + ionq.qpu + + + + + + + + + + + + + + diff --git a/src/Simulation/Simulators.Tests/TestProjects/Library with Spaces/Library with Spaces.csproj b/src/Simulation/Simulators.Tests/TestProjects/Library with Spaces/Library with Spaces.csproj index f3e9fa97083..b343833f590 100644 --- a/src/Simulation/Simulators.Tests/TestProjects/Library with Spaces/Library with Spaces.csproj +++ b/src/Simulation/Simulators.Tests/TestProjects/Library with Spaces/Library with Spaces.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 false @@ -12,9 +12,7 @@ - + diff --git a/src/Simulation/Simulators.Tests/TestProjects/Library1/Library1.csproj b/src/Simulation/Simulators.Tests/TestProjects/Library1/Library1.csproj index 6bc3becc14d..a3dc73a69ff 100644 --- a/src/Simulation/Simulators.Tests/TestProjects/Library1/Library1.csproj +++ b/src/Simulation/Simulators.Tests/TestProjects/Library1/Library1.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 diff --git a/src/Simulation/Simulators.Tests/TestProjects/Library2/Library2.csproj b/src/Simulation/Simulators.Tests/TestProjects/Library2/Library2.csproj index 6bc3becc14d..a3dc73a69ff 100644 --- a/src/Simulation/Simulators.Tests/TestProjects/Library2/Library2.csproj +++ b/src/Simulation/Simulators.Tests/TestProjects/Library2/Library2.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 diff --git a/src/Simulation/Simulators.Tests/TestProjects/QCIExe/QCIExe.csproj b/src/Simulation/Simulators.Tests/TestProjects/QCIExe/QCIExe.csproj index c6f7416e993..b822a126428 100644 --- a/src/Simulation/Simulators.Tests/TestProjects/QCIExe/QCIExe.csproj +++ b/src/Simulation/Simulators.Tests/TestProjects/QCIExe/QCIExe.csproj @@ -1,25 +1,25 @@ - - - - Library - netcoreapp3.1 - - false - false - false - true - qci.qpu - - - - - - - - - - - - - - + + + + Library + netcoreapp3.1 + + false + false + false + true + qci.qpu + + + + + + + + + + + + + + diff --git a/src/Simulation/Simulators.Tests/TestProjects/QsharpExe/QsharpExe.csproj b/src/Simulation/Simulators.Tests/TestProjects/QsharpExe/QsharpExe.csproj index 6bf3908ba0c..972b97bc6c1 100644 --- a/src/Simulation/Simulators.Tests/TestProjects/QsharpExe/QsharpExe.csproj +++ b/src/Simulation/Simulators.Tests/TestProjects/QsharpExe/QsharpExe.csproj @@ -1,4 +1,4 @@ - + Exe diff --git a/src/Simulation/Simulators.Tests/TestProjects/TargetedExe/Program.qs b/src/Simulation/Simulators.Tests/TestProjects/TargetedExe/Program.qs new file mode 100644 index 00000000000..c08b6d4188b --- /dev/null +++ b/src/Simulation/Simulators.Tests/TestProjects/TargetedExe/Program.qs @@ -0,0 +1,16 @@ +namespace Microsoft.Quantum.Testing.Honeywell.Monomorphization { + + open Microsoft.Quantum.Intrinsic; + open Microsoft.Quantum.Measurement; + open Microsoft.Quantum.Canon; + + @EntryPoint() + operation CallGenerics() : String { + + let arr = Default(); + using (qs = Qubit[2]) { + Ignore(Measure([PauliX, PauliX], qs)); + return "TargetedExe"; + } + } +} diff --git a/src/Simulation/Simulators.Tests/TestProjects/TargetedExe/TargetedExe.csproj b/src/Simulation/Simulators.Tests/TestProjects/TargetedExe/TargetedExe.csproj new file mode 100644 index 00000000000..dbd623662d8 --- /dev/null +++ b/src/Simulation/Simulators.Tests/TestProjects/TargetedExe/TargetedExe.csproj @@ -0,0 +1,41 @@ + + + + Exe + netcoreapp3.1 + + false + false + false + honeywell.qpu + detailed + + + + + + + + + + + + + + + + + <_ExeDir>$(MSBuildThisFileDirectory)built + + + + + + + + <_ExeFiles Include="$(OutputPath)*" /> + + + + + diff --git a/src/Simulation/Simulators.Tests/TestProjects/UnitTests/UnitTests.csproj b/src/Simulation/Simulators.Tests/TestProjects/UnitTests/UnitTests.csproj index 93ba7b93252..0bcd2c473e4 100644 --- a/src/Simulation/Simulators.Tests/TestProjects/UnitTests/UnitTests.csproj +++ b/src/Simulation/Simulators.Tests/TestProjects/UnitTests/UnitTests.csproj @@ -1,4 +1,4 @@ - + netcoreapp3.1 diff --git a/src/Simulation/Simulators.Tests/Tests.Microsoft.Quantum.Simulators.csproj b/src/Simulation/Simulators.Tests/Tests.Microsoft.Quantum.Simulators.csproj index 3ba45db5b21..3baf54fe219 100644 --- a/src/Simulation/Simulators.Tests/Tests.Microsoft.Quantum.Simulators.csproj +++ b/src/Simulation/Simulators.Tests/Tests.Microsoft.Quantum.Simulators.csproj @@ -1,4 +1,4 @@ - + @@ -23,6 +23,9 @@ false + + false + @@ -38,12 +41,16 @@ <_ExeDir>$(MSBuildThisFileDirectory)TestProjects\QsharpExe\built\ + <_TargetedExeDir>$(MSBuildThisFileDirectory)TestProjects\TargetedExe\built\ <_ExeFiles Include="$(_ExeDir)*" /> + <_TargetedExeFiles Include="$(_TargetedExeDir)*" /> + + diff --git a/src/Simulation/Simulators.Tests/TypeExtensionsTest.cs b/src/Simulation/Simulators.Tests/TypeExtensionsTest.cs index 5fa2f260610..a7942f7f110 100644 --- a/src/Simulation/Simulators.Tests/TypeExtensionsTest.cs +++ b/src/Simulation/Simulators.Tests/TypeExtensionsTest.cs @@ -33,6 +33,16 @@ public void BasicTypes() Assert.Equal("\"\"", "".GetNonQubitArgumentsAsString()); } + [Fact] + public void OperationTypes() + { + var op = new QuantumSimulator().Get(); + Assert.Equal("H", op.GetNonQubitArgumentsAsString()); + + var op2 = new QuantumSimulator().Get(); + Assert.Equal("CNOT", op2.GetNonQubitArgumentsAsString()); + } + [Fact] public void QubitTypes() { @@ -58,6 +68,10 @@ public void TupleTypes() Assert.Equal("(\"foo\", (\"bar\", \"car\"))", ("foo", ("bar", "car")).GetNonQubitArgumentsAsString()); Assert.Equal("((\"foo\"), (\"bar\", \"car\"))", (("foo", new FreeQubit(0)), ("bar", "car")).GetNonQubitArgumentsAsString()); + var op = new QuantumSimulator().Get(); + var opTuple = new QTuple<(ICallable, string)>((op, "foo")); + Assert.Equal("(H, \"foo\")", opTuple.GetNonQubitArgumentsAsString()); + var qtuple = new QTuple<(Qubit, string)>((new FreeQubit(0), "foo")); Assert.Equal("(\"foo\")", qtuple.GetNonQubitArgumentsAsString()); } @@ -68,11 +82,18 @@ public void ArrayTypes() Assert.Equal("[1, 2, 3]", new[] { 1, 2, 3 }.GetNonQubitArgumentsAsString()); Assert.Equal("[\"foo\", \"bar\"]", new[] { "foo", "bar" }.GetNonQubitArgumentsAsString()); - var arr = new[] { + var opArr = new ICallable[] { + new QuantumSimulator().Get(), + new QuantumSimulator().Get(), + new QuantumSimulator().Get(), + }; + Assert.Equal("[H, CNOT, Ry]", opArr.GetNonQubitArgumentsAsString()); + + var qTupleArr = new[] { (new FreeQubit(0), "foo"), (new FreeQubit(1), "bar"), }; - Assert.Equal("[(\"foo\"), (\"bar\")]", arr.GetNonQubitArgumentsAsString()); + Assert.Equal("[(\"foo\"), (\"bar\")]", qTupleArr.GetNonQubitArgumentsAsString()); } [Fact] @@ -88,6 +109,10 @@ public void IApplyDataTypes() data = new ApplyData("Foo"); Assert.Equal("\"Foo\"", data.GetNonQubitArgumentsAsString()); + var op = new QuantumSimulator().Get(); + data = new ApplyData(op); + Assert.Equal("H", data.GetNonQubitArgumentsAsString()); + data = new ApplyData>((1, "foo")); Assert.Equal("(1, \"foo\")", data.GetNonQubitArgumentsAsString()); diff --git a/src/Simulation/Simulators/FindNuspecReferences.ps1 b/src/Simulation/Simulators/FindNuspecReferences.ps1 index a1fd46b8f2b..993f4b0948e 100644 --- a/src/Simulation/Simulators/FindNuspecReferences.ps1 +++ b/src/Simulation/Simulators/FindNuspecReferences.ps1 @@ -19,7 +19,7 @@ # nuget is tracking this problem at: https://github.com/NuGet/Home/issues/4491 ######################################## -$target = "Microsoft.Quantum.Simulators.nuspec" +$target = Join-Path $PSScriptRoot "Microsoft.Quantum.Simulators.nuspec" if (Test-Path $target) { Write-Host "$target exists. Skipping generating new one." @@ -28,7 +28,7 @@ if (Test-Path $target) { # Start with the nuspec template -$nuspec = [xml](Get-Content "Microsoft.Quantum.Simulators.nuspec.template") +$nuspec = [xml](Get-Content (Join-Path $PSScriptRoot "Microsoft.Quantum.Simulators.nuspec.template")) $dep = $nuspec.CreateElement('dependencies', $nuspec.package.metadata.NamespaceURI) function Add-PackageReferenceIfNew($ref) diff --git a/src/Simulation/Simulators/Microsoft.Quantum.Simulators.csproj b/src/Simulation/Simulators/Microsoft.Quantum.Simulators.csproj index 888406e6434..39777a7a57d 100644 --- a/src/Simulation/Simulators/Microsoft.Quantum.Simulators.csproj +++ b/src/Simulation/Simulators/Microsoft.Quantum.Simulators.csproj @@ -1,4 +1,4 @@ - + @@ -25,12 +25,6 @@ - - Microsoft.Quantum.Simulator.Runtime.dll - PreserveNewest - false - - runtimes\win-x64\native\%(RecursiveDir)%(FileName)%(Extension) PreserveNewest