Qualtran icon indicating copy to clipboard operation
Qualtran copied to clipboard

Propagate rotation epsilon in gate cost

Open mpharrigan opened this issue 1 year ago • 4 comments

The t_complexity protocol ignores the eps parameter when counting rotations.

The solution is to enhance the QECGatesCost cost and associated dataclass GateCounts to count rotation/eps pairs.

mpharrigan avatar Aug 05 '24 20:08 mpharrigan

Sample code snippet:

import sympy
from qualtran.bloqs.basic_gates import ZPowGate

t, eps = sympy.symbols(r"t \epsilon")
bloq = ZPowGate(exponent=t, eps=eps)
print(bloq.t_complexity())

Prints TComplexity(rotations=1).

One could do bloq.t_complexity().t_incl_rotations(eps), but this eps is not the same as the bloq's eps (which in general could be different for each subbloq).

anurudhp avatar Aug 05 '24 20:08 anurudhp

Some history:

eps for rotations was introduced in the early days of Qualtran and I think is a useful parameter when constructing rotation bloqs. I agree it's probably not propagated correctly everywhere (though I remember implementing and correctly propagating eps in qvr, qft and hamming weight phasing bloq) -- we should file issues and try to get that fixed.

Originally, the rotation bloqs had a _t_complexity_ method implemented and would return the number of T gates scaling with log(1/eps); so the T-counts for call graphs with rotation bloqs would take the eps in account. (eg: https://github.com/quantumlib/Qualtran/pull/469)

As part of unifying / deprecating the T-complexity protocol; a temporary fix was to return rotations=1 for all rotation bloqs and add a method on the TComplexity class to convert rotations into T-gates. Eventually, the idea was to use the new costing framework to keep track of bloq counts and then use the eps to convert rotation bloqs to t-gates like we used to do originally. Here are some relevant discussions - https://github.com/quantumlib/Qualtran/issues/662#issuecomment-1949215534 https://github.com/quantumlib/Qualtran/pull/678#discussion_r1492944645

Using a single / hardcoded eps to convert all rotation bloqs to t gates was never meant to be a permanent solution. We've just not gotten around completing the migration yet I guess.

tanujkhattar avatar Aug 20 '24 21:08 tanujkhattar

@mpharrigan As per our discussion offline, it'll be nice to have this as part of the v1.0 milestone.

tanujkhattar avatar Sep 05 '24 17:09 tanujkhattar

I would also please like to have this feature!

Results such as the ones produced by this code snipet:

from qualtran.bloqs.basic_gates import Ry
from qualtran.cirq_interop.t_complexity_protocol import t_complexity

for eps in [1e-11, 1e-3]:
    print(f"t_cost at eps={eps}:", t_complexity(Rx(angle, eps=eps)).t_incl_rotations())

are pretty confusing at first. I know this can be "fixed" by passing eps=eps to .t_incl_rotations() but this is not elegant.

Moreover, imagine one wants to get T gate counts for Bloqs containing rotations with different level of precision. To my understanding this is currently not possible:

from qualtran import Bloq, BloqBuilder
from qualtran.drawing import show_bloq
from qualtran.cirq_interop.t_complexity_protocol import t_complexity

class TwoRotations(Bloq):
    @property
    def signature(self):
        return Signature([
            Register('x', QBit()),
        ])

    def build_composite_bloq(self, bb: BloqBuilder, *, x):
        x = bb.add(Rx(angle=0.1, eps=1e-11), q=x)
        x = bb.add(Ry(angle=0.2, eps=1e-3), q=x)
        return {'x': x}

two_rotations = TwoRotations()

show_bloq(two_rotations)
show_bloq(two_rotations.decompose_bloq())

t_complexity(two_rotations).t_incl_rotations()

This will always output 2 * 52 = 104 even though, due to the lower precision of the Ry rotation the T count should be lower.

Or is there a way to get correct resource estimates in such cases?

cvjjm avatar Jan 16 '25 08:01 cvjjm