5
$\begingroup$

I have a Q# operation:

    operation init_and(a: Qubit, b: Qubit, target: Qubit) : Unit is Adj {
        // Uncomment this when using Toffoli simulator.
        // CCNOT(a, b, target);

        // Uncomment this when doing resource estimates.
        body(...) {
            CCNOT(a, b, target);
        }
        adjoint(...) {
            H(target);
            if (M(target) == One) {
                CZ(a, b);
            }
        }
    }

As you can see from the comments, I have to choose between being able to simulate the operation (when testing the correctness of constructions using it) and being able to correctly cost the operation (because uncomputing it should cost zero T gates).

Is there some way to get the best of both worlds? For example, some way to say "when testing correctness use this, when doing cost estimates use this"? Some way to query "Is the Hadamard available?"?

$\endgroup$
5
$\begingroup$

One possibility is to override a default implementation using an alternative one for a specific simulator. Here, init_and would be the default implementation as in the uncommented code and CCNOT would be the alternative.

In the Q# libraries, we have the exact same case for Microsoft.Quantum.Canon.ApplyAnd and Microsoft.Quantum.Canon.ApplyLowDepthAnd. Here is a cut down version of https://github.com/microsoft/QuantumLibraries/blob/main/Standard/src/Canon/And.cs:

#nullable enable

using System;
using Microsoft.Quantum.Simulation.Core;
using Microsoft.Quantum.Simulation.Simulators;

namespace SameNameSpaceAsQSharpInitAnd {
    public partial class init_and {
        public class Native : init_and {
            private bool use_classical_adjoint;

            public Native(IOperationFactory m) : base(m) {
                use_classical_adjoint = m is ToffoliSimulator;
            }

            public override Func<(Qubit, Qubit, Qubit), QVoid> __AdjointBody__ {
                get {
                    if (use_classical_adjoint) {
                        return base.__Body__;
                    }
                    return base.__AdjointBody__;
                }
            }

        }
    }
}

In your case overrides for __ControlledBody__ and __ControlledAdjointBody__ are not required.

The C# code needs to be implemented in the same project and namespace where you implement the init_and Q# operation.

$\endgroup$
0
2
$\begingroup$

Here is currently how I get this done. I have a Q# file that defines an operation is_toffoli_simulator which is then overriden in a C# file. Then I can use that operation in any method I want, instead of having to do something special for each method. The main downside is that because is_toffoli_simulator returns a value, it prevents the automatic creation of an adjoint.

In Q#:

namespace Hackery {
    operation is_toffoli_simulator() : Bool {
        // HACK: overriden in C# file.
        return false;
    }
}

In C#:

#nullable enable

using System;
using Microsoft.Quantum.Simulation.Core;
using Microsoft.Quantum.Simulation.Simulators;

namespace Hackery {
    public partial class is_toffoli_simulator {
        public class Native : is_toffoli_simulator {
            private Func<QVoid, bool> _body;

            public Native(IOperationFactory m) : base(m) {
                var b = m is ToffoliSimulator;
                _body = args => b;
            }

            public override Func<QVoid, bool> __Body__ => _body;
        }
    }
}

At which point you can do:

    operation init_and(a: Qubit, b: Qubit, target: Qubit) : Unit is Adj {
        body(...) {
            CCNOT(a, b, target);
        }
        adjoint(...) {
            if (is_toffoli_simulator()) {
                CCNOT(a, b, target);
            } else {
                H(target);
                if (M(target) == One) {
                    CZ(a, b);
                }
            }
        }
    }
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.