Context
I am implementing the quantum singular value transformation (QSVT) algorithm, see Lin Lin's lecture chapter 8.3 and the circuit is the following:
Figure 8.1. Circuit of quantum singular value transformation to construct $U_{P^\diamond_{Re}} \in BE_{1,m+1}(P^\diamond_{Re}(A))$, using $U_A \in BE_{1,m}(A)$.
$|0^m>$ are the ancillas of the block encoding $U_A$.
The Issue
To translate that into Qualtran, I define a class QSVT(blockEncoding) that takes a blockEncoding. It is easy to define a correct signature, for example:
bloqEnc : BlockEncoding
def signature(self):
return Signature([
Register("signal", QBit()),
Register("ancilla", QAny(self.bloqEnc.ancilla_bitsize)),
Register("system", QAny(self.bloqEnc.system_bitsize)),
])
But when implementing the build_composite_bloq(), I run into the following problem:
signal, ancilla = bb.add(controlled_rotation_bloq, target=signal, ctrl=ancilla)
ancilla, system = bb.add(bloqEnc, what_to_put_here=ancilla, what_to_put_here=system)
To make this generic, I would need either the names or ordering of the registers expected by an arbitrary block encoding. But the current BlockEncoding interface gives no guarantees about either.
I may be missing something, maybe there is a method to use bb.add correctly, but add_t and add_d don't seem to work here.
One other solution is to create a new interface, child of the BlockEncoding interface, but it seems impractical, every time someone needs to use QSVT they will need to use this other interface.
I could also impose a naming convention myself and throw an error if it is not respected, but this defeats the purpose of a general interface.
I saw that the LinearCombination bloq automatically wraps block encodings using AutoPartition. That might be the best solution, but it feels like a big overhead to do this every time we want to work with general block encodings.
I feel like the cleanest solution would be to change the BlockEncoding interface so that every block encoding must have standard system and ancilla registers (maybe a resource register as well). We know that every block encoding will have a system register and an ancilla register (except in the edge case where the matrix you are block encoding is unitary).
I also saw that this was the case before the commit 0d45c82, so there must be a reason for this design choice.
The only downside I can see in changing the BlockEncoding interface is the amount of refactoring required.
Context
I am implementing the quantum singular value transformation (QSVT) algorithm, see Lin Lin's lecture chapter 8.3 and the circuit is the following:
Figure 8.1. Circuit of quantum singular value transformation to construct$U_{P^\diamond_{Re}} \in BE_{1,m+1}(P^\diamond_{Re}(A))$ , using $U_A \in BE_{1,m}(A)$ .
The Issue
To translate that into Qualtran, I define a
class QSVT(blockEncoding)that takes ablockEncoding. It is easy to define a correct signature, for example:But when implementing the
build_composite_bloq(), I run into the following problem:To make this generic, I would need either the names or ordering of the registers expected by an arbitrary block encoding. But the current
BlockEncodinginterface gives no guarantees about either.I may be missing something, maybe there is a method to use
bb.addcorrectly, butadd_tandadd_ddon't seem to work here.One other solution is to create a new interface, child of the
BlockEncodinginterface, but it seems impractical, every time someone needs to use QSVT they will need to use this other interface.I could also impose a naming convention myself and throw an error if it is not respected, but this defeats the purpose of a general interface.
I saw that the
LinearCombinationbloq automatically wraps block encodings usingAutoPartition. That might be the best solution, but it feels like a big overhead to do this every time we want to work with general block encodings.I feel like the cleanest solution would be to change the BlockEncoding interface so that every block encoding must have standard
systemandancillaregisters (maybe a resource register as well). We know that every block encoding will have a system register and an ancilla register (except in the edge case where the matrix you are block encoding is unitary).I also saw that this was the case before the commit 0d45c82, so there must be a reason for this design choice.
The only downside I can see in changing the BlockEncoding interface is the amount of refactoring required.