The problem
It's typical pattern when we have a loop where each iteration produces circuits that are very similar or identical. So for resource estimation we can only run estimation for first iteration and multiply by number of iterations (this is done to get resource estimates quickly without building full circuit).
We already have Std.ResourceEstimation.RepeatEstimates for that, but I am not satisfied with it. The problem is that if we use it, it will only one iteration once, even when we are in "run" mode (e.g. simulating) - which will produce wrong result in simulation. So, I have to write two separate implementations - one for run, one for estimation.
I would like to be able to write a loop in such a way that it will be executed correctly (n times) during simulation, but will be executed only once during resource estimation.
Proposed solution
- Introduce a helper in
Std.ResourceEstimation.Loop that I can use instead of a for loop:
operation Loop(num_iterations : Int, iteration : ((Int) => Unit)) : Unit {
if (IsResourceEstimating()) {
within {
Std.ResourceEstimation.RepeatEstimates(num_iterations);
} apply {
iteration(0);
}
} else {
for i in 0..num_iterations-1 {
iteration(i);
}
}
}
In 'run' mode Loop(n, i => { SOME_CODE }); is equivalent to for i in 0..n-1 { SOME_CODE }. However, in 'estimate' mode this will only run first iteration and scale it by n.
- Also introduce a helper
Std.ResourceEstimation.IsResourceEstimating which is a boolean function returning true if code runs in resource estimation mode. I propose that it should be implemented as intrinsic. However, I found very hacky way to implement it purely in Q# (which is a workaround I am using now):
// Idea: in "Run" mode BeginEstimateCaching ALWAYS returns true.
// In "Estimate" mode BeginEstimateCaching returns false starting from second time.
function IsResourceEstimating() : Bool {
if (Std.ResourceEstimation.BeginEstimateCaching("IsResourceEstimating", 0)) {
// Either "run" mode or first check in "estimate".
Std.ResourceEstimation.EndEstimateCaching();
} else {
// Subsequent check in "estimate mode".
return true;
}
if (Std.ResourceEstimation.BeginEstimateCaching("IsResourceEstimating", 0)) {
// Definitely "run" mode.
Std.ResourceEstimation.EndEstimateCaching();
return false;
} else {
// Subsequent check in "estimate mode".
return true;
}
}
Additional context
- This pattern is common in arithmetic circuits such as multiplication and exponentiation.
- If adding
Loop helper is not desirable, I'd like to at least add IsResourceEstimating helper, as I find it useful (even beyond this use case) to be able to check whether we are in "run" or " estimate mode. As I demonstrated, it's already possible to extract this information in runtime, but there is no officially supported API for that.
- I am happy to send PR to implement this if the code owners confirm this will be accepted and suggest what are good names for these 2 functions.
The problem
It's typical pattern when we have a loop where each iteration produces circuits that are very similar or identical. So for resource estimation we can only run estimation for first iteration and multiply by number of iterations (this is done to get resource estimates quickly without building full circuit).
We already have
Std.ResourceEstimation.RepeatEstimatesfor that, but I am not satisfied with it. The problem is that if we use it, it will only one iteration once, even when we are in "run" mode (e.g. simulating) - which will produce wrong result in simulation. So, I have to write two separate implementations - one for run, one for estimation.I would like to be able to write a loop in such a way that it will be executed correctly (n times) during simulation, but will be executed only once during resource estimation.
Proposed solution
Std.ResourceEstimation.Loopthat I can use instead of a for loop:In 'run' mode
Loop(n, i => { SOME_CODE });is equivalent tofor i in 0..n-1 { SOME_CODE }. However, in 'estimate' mode this will only run first iteration and scale it byn.Std.ResourceEstimation.IsResourceEstimatingwhich is a boolean function returning true if code runs in resource estimation mode. I propose that it should be implemented as intrinsic. However, I found very hacky way to implement it purely in Q# (which is a workaround I am using now):Additional context
Loophelper is not desirable, I'd like to at least addIsResourceEstimatinghelper, as I find it useful (even beyond this use case) to be able to check whether we are in "run" or " estimate mode. As I demonstrated, it's already possible to extract this information in runtime, but there is no officially supported API for that.