2
$\begingroup$

I want to create a unit test in Q# that runs an operation and asserts that it used at most 10 Toffoli operations. How do I do this?

For example, what changes do I have to make to the code below?

namespace Tests {
    open Microsoft.Quantum.Diagnostics;
    open Microsoft.Quantum.Intrinsic;

    operation op() : Unit {
        using (qs = Qubit[3]) {
            for (k in 0..10) {
                CCNOT(qs[0], qs[1], qs[2]);
            }
        }
    }

    @Test("ResourcesEstimator")
    operation test_op_toffoli_count_at_most_10() : Unit {
        ...?
        op();
        ...?
        if (tof_count > 10) {
            fail "Too many Toffolis";
        }
    }
}
```
$\endgroup$
2
  • $\begingroup$ What is the op() function made to do ? There is no input, and the 3 qubits are stil in the state : $|000\rangle$ $\endgroup$ Nov 27 '20 at 10:50
  • $\begingroup$ @Jonathcraft it's meant to be a trivial example, nothing else. $\endgroup$ Nov 27 '20 at 17:17
2
$\begingroup$

There are multiple ways to do this, depending on what exactly you want to check.

  1. Using AllowAtMostNCallsCA library operation.

The easiest way (with the code short enough to be included) is applicable if you know that you only use CCNOT gates when you want a Toffoli gate, and you never use Controlled X gates. In this case you can AllowAtMostNCallsCA operation that enforces exactly that:

namespace Tests {
    open Microsoft.Quantum.Diagnostics;
    open Microsoft.Quantum.Intrinsic;

    operation op() : Unit {
        using (qs = Qubit[3]) {
            for (k in 0..10) {
                CCNOT(qs[0], qs[1], qs[2]);
            }
        }
    }

    @Test("ResourcesEstimator")
    operation test_op_toffoli_count_at_most_10() : Unit {
        within {
            AllowAtMostNCallsCA(10, CCNOT, "Too many Toffolis");
        } apply {
            op();
        }
    }
}

This test will fail right away, and that's how you can notice that the loop actually uses 11 CCNOTs. However, if you replace the CCNOTs in the loop body with Controlled X([qs[0], qs[1]], qs[2]); (which is exactly the same gate), the test will happily pass irrespective of how many times you use the gate.

  1. Using resource estimator.

You can write a test (it will have to be in a different language, though) that will invoke ResourcesEstimator, run an operation using it, extract the statistics and analyze them. I don't have a ready example on hand; the closest thing is this documentation. This approach has the advantage of matching the resource estimates done by ResourcesEstimator exactly, rather than tracking specific gates.

  1. Using custom simulator.

If you want to do some sophisticated checks, for example, count all gates that act on exactly 3 qubits and limit their number, you can write your own simulator that would extend the simulator you like by doing some extra counting whenever an operation is called. This simulator could expose access to those statistics to your Q# code, so you could write custom assertions using this data. I'm not including the full code here, since it's pretty lengthy (and you indicated that you don't want to use a second language); you can find a complete example here (some tasks in the Quantum Katas use tests like "prohibit all multi-qubit operations except Measure", so this simulator comes handy).

$\endgroup$
0
$\begingroup$

The way I can think of is using the ressource estimator. By using a python or C# host file, you can use the ressource simulator and store its value. In python, for example, the ressource estimator will return a dictionary containing the number of single qubit Pauli or Clifford gates under the key [QubitClifford]. You could then use a simple if condition to check if the number of Pauli gates is under 10. If you want to know more about unit tests, I asked this question a couple of weeks ago.

I hope this could help.

$\endgroup$
2
  • $\begingroup$ Using a second language is not ideal, but doable. However, I'm looking for actual code in the answer. $\endgroup$ Nov 27 '20 at 10:29
  • $\begingroup$ Sorry, I just realised this solution didn't work, I will try to think about it and correct myself $\endgroup$ Nov 27 '20 at 12:06

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.