PsiQ / bartiq

Bartiq
https://psiq.github.io/bartiq/
Apache License 2.0
29 stars 9 forks source link

Implement handling of loops over qubit registers #51

Open dexter2206 opened 3 months ago

dexter2206 commented 3 months ago

Consider a circuit as depicted in the image below. image Here, both a and b are four-qubit registers. The X-gate is applied to each qubit of a controlled by the corresponding qubit in b, which can be written as following pseudocode:

for i in range(len(a)):
    a[i].x().controlled_by(b[i])

Currently, implementing such a loop in Bartiq is not straightforward, and might be achieved as follows:

The structure of such operation would then look like this: image

What can we do? If we find that this is an operation that the users commonly use, we should try coming up with an easier and less involved way of defining such loop in Bartiq.

For reference, this is the QREF yaml used to generate the diagram above:

version: v1
program:
  name: loop
  ports:
  - {name: in_a, size: N, direction: input}
  - {name: out_a, size: N, direction: output}
  - {name: in_b, size: N, direction: input}
  - {name: out_b, size: N, direction: output}
  children:
  - name: op
    ports:
    - {name: in_a_i, size: 1, direction: input}
    - {name: out_a_i, size: 1, direction: output}
    - {name: in_b_i, size: 1, direction: input}
    - {name: out_b_i, size: 1, direction: output}
  - name: split_a
    ports:
    - {name: in_a, size: N, direction: input}
    - {name: out_a_i, size: 1, direction: output}
    - {name: out_a_rest, size: N-1, direction: output}
  - name: split_b
    ports:
    - {name: in_b, size: N, direction: input}
    - {name: out_b_i, size: 1, direction: output}
    - {name: out_b_rest, size: N-1, direction: output}
  - name: merge_a
    ports:
    - {name: out_a, size: N, direction: output}
    - {name: in_a_i, size: 1, direction: input}
    - {name: in_a_rest, size: N-1, direction: input}
  - name: merge_b
    ports:
    - {name: out_b, size: N, direction: output}
    - {name: in_b_i, size: 1, direction: input}
    - {name: in_b_rest, size: N-1, direction: input}
  connections:
  - {source: in_a, target: split_a.in_a}
  - {source: split_a.out_a_i, target: op.in_a_i}
  - {source: in_b, target: split_b.in_b}
  - {source: split_b.out_b_i, target: op.in_b_i}
  - {source: split_a.out_a_rest, target: merge_a.in_a_rest}
  - {source: op.out_a_i, target: merge_a.in_a_i}
  - {source: split_b.out_b_rest, target: merge_b.in_b_rest}
  - {source: op.out_b_i, target: merge_b.in_b_i}
  - {source: merge_a.out_a, target: out_a}
  - {source: merge_b.out_b, target: out_b}