Skip to content

Conversation

@isaacdevlugt
Copy link
Contributor

@isaacdevlugt isaacdevlugt commented Oct 1, 2025

Context: QRAM implementation based on https://arxiv.org/pdf/2502.06767

Description of the Change: Adds QRAMtemplate, tests, and documentation

Benefits:

Possible Drawbacks:

Related GitHub Issues:

@github-actions
Copy link
Contributor

github-actions bot commented Oct 1, 2025

Hello. You may have forgotten to update the changelog!
Please edit doc/releases/changelog-dev.md with:

  • A one-to-two sentence description of the change. You may include a small working example for new features.
  • A link back to this PR.
  • Your name (or GitHub username) in the contributors section.


.. gallery-item::
:description: :doc:`QRAM <../code/api/pennylane.QRAM>`
:figure: _static/templates/TODO
Copy link
Contributor Author

Choose a reason for hiding this comment

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

TODO

Copy link
Contributor

@comp-phys-marc comp-phys-marc Nov 18, 2025

Choose a reason for hiding this comment

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

Curious how this image will be provided? Where will it come from?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Screenshot 2025-11-18 at 1 05 45 PM

I don't think it needs to be more complicated than this^ 🤔

Copy link
Contributor

Choose a reason for hiding this comment

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

Any reason we say QROM here rather than QRAM?

Copy link
Contributor

Choose a reason for hiding this comment

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

Just using this image for now...

Copy link
Contributor

Choose a reason for hiding this comment

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

Ok I have permission from Josh and Tarik to take a shot at creating the QRAM template in inkscape. I will make one that closely matches the above.

Copy link
Contributor

Choose a reason for hiding this comment

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

qram_thumbnail

@isaacdevlugt isaacdevlugt changed the title open PR QRAM template Oct 1, 2025
work_wires (Sequence[int]): the auxiliary wires used for the computation
clean (bool): if True, the work wires are not altered by operator, default is ``True``
..see-also:: :class:`~.QRAM`, :class:`~.QROMStatePreparation`
Copy link
Contributor Author

@isaacdevlugt isaacdevlugt Oct 1, 2025

Choose a reason for hiding this comment

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

TODO: update name of QRAM class if needed

Copy link
Contributor

Choose a reason for hiding this comment

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

Done!

Copy link
Contributor

@comp-phys-marc comp-phys-marc left a comment

Choose a reason for hiding this comment

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

Some really great work here. My initial thoughts / questions!

Comment on lines 193 to 199
for p in range(1 << k):
#change to in_wire later
parent = _node_index(k - 1, p >> 1)
if p % 2 == 0:
ops.append(qml.SWAP(wires =[self.portL_wires[parent], self._router(k, p)]))
else:
ops.append(qml.SWAP(wires =[self.portR_wires[parent], self._router(k, p)]))
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there a bit of duplication of logic between here and _route_bus_down_first_k_levels?

Comment on lines 216 to 220
op0 = qml.CSWAP(wires=[d, in_w, R])
ops.append(op0)
# dir==0 ⇒ SWAP(in, L)
op = qml.SWAP(wires=[in_w, L])
ops.append(qml.ctrl(op, control=[d], control_values=[0]))
Copy link
Contributor

Choose a reason for hiding this comment

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

I am not sure why we sometimes use CSWAP and sometimes use ctrl(SWAP, ...)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If there's truly no difference we can easily replace with whatever is most efficient :)

Copy link
Contributor

Choose a reason for hiding this comment

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

There will be no material difference. Just a matter of picking something and sticking with it.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think the reason we use ctrl here is because it takes control_values, right?

Comment on lines 228 to 266
# def _route_bus_down(self) -> list:
# """Route the bus from root to leaf across all levels using dir-controlled CSWAPs."""
# ops = []
# for k in range(self.n_k):
# for p in range(1 << k):
# in_w = self._node_in_wire(k, p)
# L = self._portL(k, p)
# R = self._portR(k, p)
# d = self._router(k, p)
# if k == 0:
# upper_ctrls, upper_vals = [], []
# else:
# upper_ctrls = [self._router(j, p >> (k - j)) for j in range(k)]
# upper_vals = [(p >> (k - 1 - j)) & 1 for j in range(k)]
# op0 = qml.SWAP(wires=[in_w, L])
# op1 = qml.SWAP(wires=[in_w, R])
# ops.append(
# qml.ctrl(op0, control=[d] + upper_ctrls, control_values=[0] + upper_vals)
# if upper_ctrls
# else qml.ctrl(op0, control=[d], control_values=[0])
# )
# ops.append(
# qml.ctrl(op1, control=[d] + upper_ctrls, control_values=[1] + upper_vals)
# if upper_ctrls
# else qml.ctrl(op1, control=[d], control_values=[1])
# )
# return ops

# def _route_bus_up(self) -> list:
# """Inverse of `_route_bus_down`."""
# return list(reversed(self._route_bus_down()))

# # ---------- Select controls----------
# def _select_ctrls(self, s: int):
# if self.k == 0:
# return [], []
# ctrls = list(self.select_wires)
# vals = [(s >> (self.k - 1 - j)) & 1 for j in range(self.k)]
# return ctrls, vals
Copy link
Contributor

Choose a reason for hiding this comment

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

What is the story / plan with all this commented out code?

Comment on lines 60 to 62
class SelectBucketBrigadeBusQRAM(qml.operation.Operation):
r"""Bucket-brigade QRAM with **explicit bus routing** using 3 qubits per node,
and an optional **select (MSB) prefix**, plus **hybrid** support.
Copy link
Contributor

Choose a reason for hiding this comment

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

The one part of Bucket Brigade QRAM I am still unclear about is how once we have traversed the tree and have an active path from the root to a leaf, we actually translate this to a loading of the corresponding data into the data register?

Choose a reason for hiding this comment

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

The BB QRAM undergoes three steps to query the data, including address loading, data retrieval, and address unloading. Address loading can be understood as a unitary operation that implements a transformation between binary encoding and unary encoding. Data retrieval, where the loading of the corresponding data happens, directly applies the data for each entry in the unary encoding to the corresponding location. Since unary encoding every entry in the address has seperated qubits, such loading won't affect each other. Finally the unloading of the address ``compress'' the encoding back into binary and finish the query.

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks!

portL_wires: Sequence[int],
portR_wires: Sequence[int],
*,
mode: str = "quantum",
Copy link
Contributor

Choose a reason for hiding this comment

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

What is the benefit of hybrid mode? Is it merely a trade-off of qubit count versus speedup?

Copy link
Contributor

Choose a reason for hiding this comment

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

What is the advantage of being able to do an access in superposition?

Choose a reason for hiding this comment

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

Basically yes, it is trade off between qubit and time

)

# -----------------------------
# TODOs / Extensions
Copy link
Contributor

Choose a reason for hiding this comment

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

Are these TODOs something we can help with? How would we like to plan out and distribute this work?

@comp-phys-marc
Copy link
Contributor

I also just want to invite @albi3ro to share any of the thoughts she had on refactoring / structuring this code. :)

else:
target = self._portR(self.n_k - 1, p >> 1)
bit = self.bitstrings[p][j]
if bit == "1":
Copy link
Contributor

@comp-phys-marc comp-phys-marc Nov 18, 2025

Choose a reason for hiding this comment

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

How will the leaves' ops need to be handled once we actually have this template running on a quantum backend? Will there need to be a change?

@comp-phys-marc
Copy link
Contributor

Is there value in making this capture compatible?

ops.append(SWAP(wires=[tw, self.bus_wire[0]]))
return ops

# not work yet
Copy link
Contributor

Choose a reason for hiding this comment

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

I am curious what about this decomposition particularly doesn't work yet?

ops += self._unmark_routers_via_bus()
return ops

# Not work yet
Copy link
Contributor

Choose a reason for hiding this comment

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

Curious also about what in particular doesn't work about this decomposition yet.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants