XanaduAI / strawberryfields

Strawberry Fields is a full-stack Python library for designing, simulating, and optimizing continuous variable (CV) quantum optical circuits.
https://strawberryfields.ai
Apache License 2.0
754 stars 191 forks source link

Adjusting UI for measurement on several modes #403

Open antalszava opened 4 years ago

antalszava commented 4 years ago

Issue description

Strawberry Fields allows having multi-mode measurements in a Program by having measurement operators targetting several registers that reference the modes to be measured.

Within the definition of a program, this means having MeasurementOperator | (q[0], q[1], q[2], ...) , where q[0], q[1], ... refer to the registers of the modes to be measured.

Intuitively, one could want to define the same measurement by having consecutive measurement operators targetting a single register in the following fashion:

    MeasurementOperator | q[0]
    MeasurementOperator | q[1]
    MeasurementOperator | q[2]
    (...)

Specific example Let's have a look at a specific example, where it is expected to see correlation between the outcomes for each mode

  1. Running the following example:
    prog = sf.Program(2)
    eng = sf.Engine("gaussian")
    with prog.context as q:
    S2gate(1) | (q[0], q[1])
    MeasureFock() | (q[0], q[1])
    results = eng.run(prog, shots=5)
    results.samples

    can result in an output like:

    array([[1, 1],
       [4, 4],
       [1, 1],
       [0, 0],
       [1, 1]])
  2. This is in contrast with the following Program definition:
    prog = sf.Program(2)
    eng = sf.Engine("gaussian")
    with prog.context as q:
    S2gate(1) | (q[0], q[1])
    MeasureFock() | q[0]
    MeasureFock() | q[1]
    results = eng.run(prog, shots=5)
    results.samples

    which can result in an output like:

    array([[1, 1],
       [0, 1],
       [1, 2],
       [3, 0],
       [2, 4]])

    With the second example, mode q[0] gets reinitialized to the vacuum state after being measured.

Python version: 3.7.6 Platform info: Linux-4.19.11-041911-generic-x86_64-with-debian-buster-sid Installation path: /anaconda3/lib/python3.7/site-packages/strawberryfields Strawberry Fields version: 0.14.0 Numpy version: 1.18.4 Scipy version: 1.4.1 SymPy version: 1.5.1 NetworkX version: 2.3 The Walrus version: 0.12.0 Blackbird version: 0.2.3 TensorFlow version: 2.0.0



#### Additional information

This would most likely include a change in how compilers handle measurement operators and introduce logic so that compilers will automatically group measurements that are terminal.
josh146 commented 4 years ago

Also worth mentioning that while this is unintuitive, it is also expected behaviour; the backend API was designed such that after a measurement operation, the mode is always traced out and replaced with the vacuum state. This allows the state to be re-used without needing to add additional modes to the system, which might be costly.

I propose that we simply modify the compilers such that terminal measurements of a program (e.g, those that are 'dangling' nodes of the DAG with no other operations depending on them) are compiled into a single measurement result.

That is,

Sgate(0.5) | q[0]
MeasureX  | q[0]
S2gate(q[0].par) | (q[0], q[1])
MeasureFock() | q[0]
Xgate(0.5) | q[2]
MeasureFock() | q[1]
MeasureX | q[2]

would be compiled to give

Sgate(0.5) | q[0]
MeasureX  | q[0]
S2gate(q[0].par) | (q[0], q[1])
Xgate(0.5) | q[2]
MeasureFock() | (q[0], q[1])
MeasureX | q[2]

where the two terminal fock measurements are combined, but the non-terminal MeasureX in the middle of the circuit is not.

felipeoyarce commented 3 years ago

Hi @antalszava and @josh146 ! I would like to work on this issue :hugs:

josh146 commented 3 years ago

Hi @felipeoyarce, nice! Feel free to open a WIP PR, and ask any questions as they arise :)