Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Constructing a series of And gates with same target but different control #1445

Open
kjm538 opened this issue Oct 7, 2024 · 2 comments
Open

Comments

@kjm538
Copy link

kjm538 commented Oct 7, 2024

Consider the following bloq which yields one And gate per qubit in the control register, all with the same target.

@attrs.frozen
class myBloq(Bloq):
    bitsize: int

    @cached_property
    def signature(self) -> Signature:
        return Signature(
            [   Register("control", QBit(), shape=(self.bitsize,)),
                Register("ancilla", QBit(), shape=(self.bitsize,)),
                Register("target", QBit(), side=Side.RIGHT),
            ]
        )

    def build_composite_bloq(
        self, bb: BloqBuilder, control, ancilla
    ):

        for i in range(self.bitsize):
            (control[i], ancilla[i]), target = bb.add(And(cv1=1,cv2=0),ctrl=[control[i],ancilla[i]])

        return {'control': control,'ancilla': ancilla, 'target': target}

At first this may seem wrong since the target of the And gate must be clean by definition, and trying to decompose this bloq does lead to the error

---------------------------------------------------------------------------
BloqError                                 Traceback (most recent call last)
      bloq_ex = myBloq(2)
----> bloq_ex.decompose_bloq()
  File "/Users/.../qualtran/_infra/bloq.py", line 142, in decompose_bloq
    return _decompose_from_build_composite_bloq(self)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/.../qualtran/_infra/bloq.py", line 52, in _decompose_from_build_composite_bloq
    return bb.finalize(**out_soqs)
           ^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/.../qualtran/_infra/composite_bloq.py", line 1072, in finalize
    return self._finalize_strict(**final_soqs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/.../qualtran/_infra/composite_bloq.py", line 1111, in _finalize_strict
    raise BloqError(
qualtran._infra.composite_bloq.BloqError: During finalization, {Soquet(binst=BloqInstance(bloq=And(cv1=1, cv2=0, uncompute=False), i=0), reg=Register(name='target', dtype=QBit(), _shape=(), side=<Side.RIGHT: 2>), idx=())} Soquets were not used.

which I think is due to this reason. However, if I have prepared my control register such that it's in a state where only one bit is 1 (ie |01> + |10> for bitsize=2), then algorithmically this construction is okay since the target will only be turned 'ON' once per state. A simple solution would be to just build my bloq using the Toffoli, however this is not ideal for resource counting purposes. Do you have any suggestions or thoughts on how to construct this?

@tanujkhattar
Copy link
Collaborator

Can you describe the action you want in more detail? If you want to flip the target when all control bits are ON (or in any given specification), you can look at MultiAnd bloq which is equivalent an n-controlled Toffoli gate.

The other possibility, which I think is what you actually want, is to compare two n-bit registers (say x & y) and check whether they are the same, -- so a bloq that implements result = all(x[i] == y[i] for i in range(self.bitsize)); or in your case result = all(x[i] != y[i] for i in range(self.bitsize)). This is a quantum-quantum comparator and can be reduced to an XOR (N CNOT gates) followed by a quantum -classical comparison with 0 (i.e. a MultiAnd) gate. Qualtran has bloqs for Xor and MultiAnd which can be used to implement your bloq.

@kjm538
Copy link
Author

kjm538 commented Oct 8, 2024

The action I want is to flip the target bit if any of the controls are satisfied. So something like result = any(x[i] != y[i] for i in range(self.bitsize)), however I only expect this to be True for one value of i for any input state due to the way I've prepared the control register.

More explicitly, I'm implementing the decomposition for TestNuLessThanMu in the first quantized block encoding. So the control register here corresponds to mu and the ancilla to one dimension of nu. In reality I have a series of MultiAnds with 4 controls ( the 1 on mu and three 0s on nu). Before this series of MultiAnds, the control/mu register has been prepared in a superposition of one-hot unary states.

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

No branches or pull requests

2 participants