For the sake of completeness: June release of Q# now offers AutoSubstitution rewrite step, which allows to substitute an implementation of an operation with a different one when running on a specific simulator. This blog post offers more details on how to use it.
The example from the question will look like this:
namespace Scratch {
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Targeting;
@SubstitutableOnTarget("Scratch.InitAndToffoli", "ToffoliSimulator")
operation InitAnd(a: Qubit, b: Qubit, target: Qubit) : Unit is Adj {
// This implementation will be called on any simulator except Toffoli
body(...) {
Message("InitAnd body");
CCNOT(a, b, target);
}
adjoint(...) {
Message("Adjoint InitAnd body");
H(target);
if (M(target) == One) {
CZ(a, b);
}
}
}
operation InitAndToffoli(a: Qubit, b: Qubit, target: Qubit) : Unit is Adj {
// This implementation will be called only on Toffoli simulator
Message("InitAndToffoli");
CCNOT(a, b, target);
}
// Make the sample complete as a standalone executable
@EntryPoint()
operation RunIt() : Unit {
use (a, b, target) = (Qubit(), Qubit(), Qubit());
InitAnd(a, b, target);
// The required workaround to make sure substitute operation
// is available to the runtime - will be removed soon.
let _ = InitAndToffoli;
}
}
Now, if you run it from command line:
dotnet run
will use default full state simulator, and print "InitAnd body"
dotnet run -s ToffoliSimulator
will use Toffoli with the substitution, and print "InitAndToffoli"
dotnet run -s ResourcesEstimator
will use resources estimator without substitution, print "InitAnd body" and the resources count.
The accompanying .csproj file looks like this (note the package reference which provides Microsoft.Quantum.Targeting
namespace):
<Project Sdk="Microsoft.Quantum.Sdk/0.18.2107153439">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Quantum.AutoSubstitution"
Version="0.18.2107153439" IsQscReference="true" />
</ItemGroup>
</Project>