diff --git a/samples/runtime/README.md b/samples/runtime/README.md index 73fadc3b8abf..78e141def3b7 100644 --- a/samples/runtime/README.md +++ b/samples/runtime/README.md @@ -2,6 +2,8 @@ These samples show how to work with the Q# simulation runtime. +- **[Auto substitution](./autosubstitution)**: + This sample uses the [`Microsoft.Quantum.AutoSubstitution` NuGet package](http://nuget.org/packages/Microsoft.Quantum.AutoSubstitution) to provide alternative operations based on the simulator that is used. - **[Oracle Emulation](./oracle-emulation)**: This sample shows how to provide accelerated simulation functionality for different Q# operations and functions. - **[Reversible simulator (simple)](./reversible-simulator-simple)**: diff --git a/samples/runtime/autosubstitution/AutoSubstitution.csproj b/samples/runtime/autosubstitution/AutoSubstitution.csproj new file mode 100644 index 000000000000..9d3c80042ca4 --- /dev/null +++ b/samples/runtime/autosubstitution/AutoSubstitution.csproj @@ -0,0 +1,10 @@ + + + Exe + netcoreapp3.1 + + + + + + diff --git a/samples/runtime/autosubstitution/AutoSubstitution.qs b/samples/runtime/autosubstitution/AutoSubstitution.qs new file mode 100644 index 000000000000..11195a0e164e --- /dev/null +++ b/samples/runtime/autosubstitution/AutoSubstitution.qs @@ -0,0 +1,48 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Sample { + open Microsoft.Quantum.Convert; + open Microsoft.Quantum.Math; + open Microsoft.Quantum.Measurement; + open Microsoft.Quantum.Canon; + open Microsoft.Quantum.Intrinsic; + open Microsoft.Quantum.Targeting; + + operation ApplyClassicalSWAP(a : Qubit, b : Qubit) : Unit is Adj + Ctl { + Message("Classical version"); + CNOT(a, b); + CNOT(b, a); + CNOT(a, b); + } + + // This attribute indicates that when running this Q# program with + // ToffoliSimulator, the operation `ApplyClassicalSWAP` is executed instead. + @SubstitutableOnTarget("Microsoft.Quantum.Sample.ApplyClassicalSWAP", "ToffoliSimulator") + operation ApplySingleDirectionSWAP(a : Qubit, b : Qubit) : Unit is Adj + Ctl { + // Note: In version 0.18.2106148911 we must explicitly reference the + // operation; otherwise, the compiler removes the operation from the + // compilation unit before the auto-substitution rewrite step is executed. + let _ = ApplyClassicalSWAP; + + Message("Quantum version"); + + // Implements a SWAP operation in which all CNOT operations have the + // same control and target qubits. + within { + CNOT(a, b); + H(a); + H(b); + } apply { + CNOT(a, b); + } + } + + @EntryPoint() + operation RunProgram() : Unit { + use a = Qubit(); + use b = Qubit(); + + ApplySingleDirectionSWAP(a, b); + } +} diff --git a/samples/runtime/autosubstitution/README.md b/samples/runtime/autosubstitution/README.md new file mode 100644 index 000000000000..fc9fa0dae9a2 --- /dev/null +++ b/samples/runtime/autosubstitution/README.md @@ -0,0 +1,39 @@ +--- +page_type: sample +languages: +- qsharp +products: +- qdk +description: "This sample uses the `Microsoft.Quantum.AutoSubstitution` NuGet package to provide alternative operations based on the simulator that is used." +--- + +# Using the AutoSubstitution rewrite step + +The `Microsoft.Quantum.AutoSubstitution` NuGet package offers an attribute `@SubstitutableOnTarget` that lets you replace one operation with another when using a particular simulator. For instance, decorating the operation `Op` with `@SubstitutableOnTarget("AltOp", "Sim")` lets the compiler perform a rewrite step that can link an operation `Op` to a set of pairs of an alternative operations `AltOp` and a simulator `Sim`, such that `AltOp` is executed as a replacement for `Op` when being invoked in `Sim`. + +[This auto substitution blog +post](https://devblogs.microsoft.com/qsharp/the-autosubstitution-rewrite-step/) +in the [Q# blog](https://devblogs.microsoft.com/qsharp/) describes this sample +in more detail. + +## Running the program + +First, run + +```shell +dotnet run +``` + +and you should see `Quantum version` as output, but when running + +```shell +dotnet run -- -s ToffoliSimulator +``` + +the program prints `Classical version` instead, since the alternative operation +is executed. + +## Manifest + +- [AutoSubstitution.qs](./AutoSubstitution.qs): The main Q# example code implementing quantum operations for this sample. +- [AutoSubstitution.csproj](./AutoSubstitution.csproj): Main Q# project for the sample. diff --git a/samples/runtime/runtime.sln b/samples/runtime/runtime.sln index 4f7ab875b4ea..14a49e94499e 100644 --- a/samples/runtime/runtime.sln +++ b/samples/runtime/runtime.sln @@ -25,6 +25,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "host", "qpic-simulator\host EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "simulator", "qpic-simulator\simulator\simulator.csproj", "{3F729B1F-4856-4AFE-91C4-69254034E464}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoSubstitution", "autosubstitution\AutoSubstitution.csproj", "{30838650-E4C2-4B91-880F-CFB502963A08}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -143,6 +145,18 @@ Global {3F729B1F-4856-4AFE-91C4-69254034E464}.Release|x64.Build.0 = Release|Any CPU {3F729B1F-4856-4AFE-91C4-69254034E464}.Release|x86.ActiveCfg = Release|Any CPU {3F729B1F-4856-4AFE-91C4-69254034E464}.Release|x86.Build.0 = Release|Any CPU + {30838650-E4C2-4B91-880F-CFB502963A08}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {30838650-E4C2-4B91-880F-CFB502963A08}.Debug|Any CPU.Build.0 = Debug|Any CPU + {30838650-E4C2-4B91-880F-CFB502963A08}.Debug|x64.ActiveCfg = Debug|Any CPU + {30838650-E4C2-4B91-880F-CFB502963A08}.Debug|x64.Build.0 = Debug|Any CPU + {30838650-E4C2-4B91-880F-CFB502963A08}.Debug|x86.ActiveCfg = Debug|Any CPU + {30838650-E4C2-4B91-880F-CFB502963A08}.Debug|x86.Build.0 = Debug|Any CPU + {30838650-E4C2-4B91-880F-CFB502963A08}.Release|Any CPU.ActiveCfg = Release|Any CPU + {30838650-E4C2-4B91-880F-CFB502963A08}.Release|Any CPU.Build.0 = Release|Any CPU + {30838650-E4C2-4B91-880F-CFB502963A08}.Release|x64.ActiveCfg = Release|Any CPU + {30838650-E4C2-4B91-880F-CFB502963A08}.Release|x64.Build.0 = Release|Any CPU + {30838650-E4C2-4B91-880F-CFB502963A08}.Release|x86.ActiveCfg = Release|Any CPU + {30838650-E4C2-4B91-880F-CFB502963A08}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE