Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
570dd47
added HammingWeightPhasingWithConfigurableAncilla and a temp test fil…
dobbse42 Oct 8, 2024
fbe76e8
Merge branch 'main' into main
dobbse42 Oct 11, 2024
431bc6d
Finished HammingWeightPhasingWithConfigurableAncilla.build_composite_…
dobbse42 Oct 16, 2024
c808bfd
Merge branch 'quantumlib:main' into main
dobbse42 Oct 16, 2024
4d84d9d
Merge branch 'main' of https://github.com/dobbse42/Qualtran_hamphase
dobbse42 Oct 16, 2024
e484cc0
Completed implementation of HammingWeightPhasingWithConfigurableAncil…
dobbse42 Oct 17, 2024
6970437
Merge branch 'main' into main
dobbse42 Oct 17, 2024
a8e4ccb
Merge branch 'main' into main
tanujkhattar Nov 25, 2024
a7397ac
Merge branch 'main' into main
dobbse42 Dec 2, 2024
d344afe
removed extraneous test file
dobbse42 Dec 2, 2024
6e16a1c
Merge branch 'main' of https://github.com/dobbse42/Qualtran_hamphase
dobbse42 Dec 2, 2024
c0601f1
implemented anurudh's counter suggestion in HWPhasing_with_configurab…
dobbse42 Feb 5, 2025
a64283b
fixed syntax error on prior commit
dobbse42 Apr 3, 2025
ac77b95
Merge branch 'main' into main
dobbse42 Apr 3, 2025
57c87ea
Added input validation
dobbse42 Apr 3, 2025
f64e8a3
Merge branch 'main' of https://github.com/dobbse42/Qualtran_hamphase
dobbse42 May 21, 2025
f5e0a7d
changed to using QECGatesCost and GateCounts for testing and swapped …
dobbse42 May 22, 2025
414a306
Implemented suggested code style changes and more detailed documentation
dobbse42 May 22, 2025
a0126a2
Separated HammingWeightPhasingWithConfigurableAncilla decomposition/f…
dobbse42 May 22, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 80 additions & 0 deletions qualtran/bloqs/rotations/hamming_weight_phasing.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,3 +209,83 @@ def _hamming_weight_phasing_via_phase_gradient() -> HammingWeightPhasingViaPhase
bloq_cls=HammingWeightPhasingViaPhaseGradient,
examples=(_hamming_weight_phasing_via_phase_gradient,),
)


@attrs.frozen
class HammingWeightPhasingWithConfigurableAncilla(GateWithRegisters):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We currently use Bloq ... GateWithRegisters is here for historical reasons

Suggested change
class HammingWeightPhasingWithConfigurableAncilla(GateWithRegisters):
class HammingWeightPhasingWithConfigurableAncilla(Bloq):

r"""
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The docstring should start with short discribtion of the quantum operation the bloq represents

Args:
bitsize: Size of input register to apply 'Z ** exponent' to.
ancillasize: Size of the ancilla register to be used to calculate the hamming weight of 'x'.
exponent: the exponent of 'Z ** exponent' to be applied to each qubit in the input register.
eps: Accuracy of synthesizing the Z rotations.

Registers:
x: A 'THRU' register of 'bitsize' qubits.

References:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you add a citation for the source of the construction?

"""

bitsize: int
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

prefer SymbolicInt here and for the other parameters

ancillasize: int
exponent: float = 1
eps: SymbolicFloat = 1e-10

@cached_property
def signature(self) -> 'Signature':
return Signature.build_from_dtypes(x=QUInt(self.bitsize))

#TODO:
'''
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the doc string should be inside the function

General strategy: find the max-bitsize number (n bits) we can compute the HW of using our available ancilla,
greedily do this on the first n bits of x, perform the rotations, then the next n bits and perform those
rotations, and so on until we have computed the HW of the entire input. Can express this as repeated calls to
HammingWeightPhasing bloqs on subsets of the input.
'''
def build_composite_bloq(self, bb: 'BloqBuilder', *, x: 'SoquetT') -> Dict[str, 'SoquetT']:
num_iters = self.bitsize // (self.ancillasize + 1)
remainder = self.bitsize - (self.ancillasize + 1) * num_iters
x = bb.split(x)
x_parts = []
for i in range(num_iters):
x_part = bb.join(x[i*(self.ancillasize+1):(i+1)*(self.ancillasize+1)], dtype=QUInt(self.ancillasize+1)) #maybe off-by-1
x_part = bb.add(HammingWeightPhasing(bitsize=self.ancillasize+1, exponent=self.exponent, eps=self.eps), x=x_part)
x_part = bb.add(HammingWeightPhasing(bitsize=self.ancillasize+1, exponent=self.exponent, eps=self.eps).adjoint(), x=x_part)
x_parts.extend(bb.split(x_part))
#remainder:
if remainder > 0:
x_part = bb.join(x[(-1*remainder):], dtype=QUInt(remainder))
x_part = bb.add(HammingWeightPhasing(bitsize=remainder, exponent=self.exponent, eps=self.eps), x=x_part)
x_part = bb.add(HammingWeightPhasing(bitsize=remainder, exponent=self.exponent, eps=self.eps).adjoint(), x=x_part)
x_parts.extend(bb.split(x_part))
#print("shape prior to flatten: ", np.shape(x_parts))
#x_parts.flatten()
''' x_parts = [
a
for x_part in x_parts
for a in x_part
]
'''
#print("shape after flatten: ", np.shape(x_parts))
for part in x:
print("next elem: ", part)
x = bb.join(x_parts, dtype=QUInt(self.bitsize.bit_length()))
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

try bb.join(np.array(x_parts), ...)

Elsewhere, we tried to be careful about accepting either lists or numpy arrays but seem to have missed this one.
#1470

return {'x': x}


def wire_symbol(self, reg: Optional[Register], idx: Tuple[int, ...] = tuple()) -> 'WireSymbol':
if reg is None:
return Text(f'HWPCA_{self.bitsize}/(Z^{self.exponent})')
return super().wire_symbol(reg, idx)

#TODO: (after build_composite_bloq)
@bloq_example
def _hamming_weight_phasing_with_configurable_ancilla() -> HammingWeightPhasingWithConfigurableAncilla:
hamming_weight_phasing_with_configurable_ancilla = HammingWeightPhasingWithConfigurableAncilla(4, 2, np.pi / 2.0)
return hamming_weight_phasing_with_configurable_ancilla


_HAMMING_WEIGHT_PHASING_WITH_CONFIGURABLE_ANCILLA_DOC = BloqDocSpec(
bloq_cls=HammingWeightPhasingWithConfigurableAncilla,
examples=(_hamming_weight_phasing_with_configurable_ancilla,),
)
18 changes: 18 additions & 0 deletions qualtran/bloqs/rotations/my_HWP_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from hamming_weight_phasing import HammingWeightPhasing, HammingWeightPhasingWithConfigurableAncilla

import numpy as np
from qualtran import Bloq, CompositeBloq, BloqBuilder, Signature, Register
from qualtran import QBit, QInt, QUInt, QAny
from qualtran.drawing import show_bloq, show_call_graph, show_counts_sigma

orig = HammingWeightPhasing(4, np.pi / 2.0)
print(orig)

mine = HammingWeightPhasingWithConfigurableAncilla(4, 2, np.pi / 2.0)
print(mine)


from qualtran.resource_counting.generalizers import ignore_split_join
hamming_weight_phasing_g, hamming_weight_phasing_sigma = mine.call_graph(max_depth=1, generalizer=ignore_split_join)
show_call_graph(hamming_weight_phasing_g)
show_counts_sigma(hamming_weight_phasing_sigma)