Describe the bug
AllowAtMostNCallsCA does not differentiate controlled and not-controlled variants of a unitary. While, let say, X and Controlled X have similar behavior, they are still different unitary and should be considered as so using AllowAtMostNCallsCA.
This was discovered while trying to replace Microsoft.Quantum.Katas.CounterSimulator by simple QuantumSimulator in the QuantumKatas repo
To Reproduce
The following code raise the AllowAtMostNCallsCA exception:
within {
AllowAtMostNCallsCA(2, Controlled X, "You are allowed to call Controlled X exactly once");
} apply {
// Apply the operation
op();
}
operation op() : Int {
using ((control, eigenstate) = (Qubit(), Qubit())) {
X(eigenstate);
within {
H(control);
} apply {
Controlled X([control], eigenstate);
}
let eigenvalue = M(control) == Zero ? 1 | -1;
Reset(eigenstate);
return eigenvalue;
}
}
The raised exception: Unhandled exception. Microsoft.Quantum.Simulation.Core.ExecutionFailException: Operation Microsoft.Quantum.Intrinsic.X was called more than the allowed 1 times:
You are allowed to call Controlled X exactly once
Expected behavior
The exception should not be raised when doing call to X while AllowAtMostNCallsCA is set to Controlled X.
In other words, X and Controlled X should be considered 2 different operations.
System information
QDK 0.13.20102604