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

Sabre with measurements #1084

Merged
merged 11 commits into from
Nov 22, 2023
Merged

Sabre with measurements #1084

merged 11 commits into from
Nov 22, 2023

Conversation

Simone-Bordoni
Copy link
Contributor

@Simone-Bordoni Simone-Bordoni commented Nov 13, 2023

Checklist:

  • Reviewers confirm new code works as expected.
  • Tests are passing.
  • Coverage does not decrease.
  • Documentation is updated.

@Simone-Bordoni
Copy link
Contributor Author

To make the Sabre transpiler work with qubits i have already modified the block decomposition to accept measurements.
Now measurements acting on more than one qubits are decomposed into single qubit measurements so that they do not interfere with the block decomposition. For now i managed to match the .result of new single qubit measurements that was having problems with the block.on_qubits method. another way to solve the problem would be to overload the .on_qubits method for measurement gates in order to return a gate pointing at the same result object. Let me know if you prefer this implementation or the one implemented now. in order to match the results for multi qubit measurement gates it will be a bit more difficult.
@stavros11 @BrunoLiegiBastonLiegi

@Simone-Bordoni
Copy link
Contributor Author

The Sabre transpiler with this PR will be able to corrrectly work with measurement gates. In particular final measurements can be given on multi qubits and registers are correctly matched. Intermediate measurements works correctly if acting on single qubits. When using multi qubit intermediate measurements they will be decomposed into single qubit measurements thus changing their register. However, as discussed with @Stavros, for now intermediate measurements are not suported on the hardware, so this issue can be addressed in the future.
As reported in #1094 there are problems with the measurement registers when both intermediate and final measurements are present in the circuit, when this issue will be solved alse sabre should be able to deal with circuits with both kind of measurements.

Copy link

codecov bot commented Nov 15, 2023

Codecov Report

All modified and coverable lines are covered by tests ✅

Comparison is base (b11a209) 100.00% compared to head (053c803) 100.00%.
Report is 10 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff            @@
##            master     #1084   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           63        63           
  Lines         8862      8903   +41     
=========================================
+ Hits          8862      8903   +41     
Flag Coverage Δ
unittests 100.00% <100.00%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Contributor

@BrunoLiegiBastonLiegi BrunoLiegiBastonLiegi left a comment

Choose a reason for hiding this comment

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

Thanks @Simone-Bordoni, just a handful of comments.

src/qibo/gates/measurements.py Outdated Show resolved Hide resolved
src/qibo/transpiler/router.py Outdated Show resolved Hide resolved
src/qibo/transpiler/router.py Outdated Show resolved Hide resolved
src/qibo/transpiler/router.py Outdated Show resolved Hide resolved
src/qibo/transpiler/router.py Outdated Show resolved Hide resolved
src/qibo/transpiler/router.py Outdated Show resolved Hide resolved
tests/test_transpiler_router.py Outdated Show resolved Hide resolved
tests/test_transpiler_router.py Outdated Show resolved Hide resolved
Copy link
Contributor

@BrunoLiegiBastonLiegi BrunoLiegiBastonLiegi left a comment

Choose a reason for hiding this comment

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

In the test_sabre_intermediate_measurements the transpiler is doing nothing I believe, as the CNOT(0,1) involves qubits that are connected already. I tried to change this to CNOT(0,2) to trigger the SWAP insertion and it fails for me. I would change that test by adding the measurement to qubit 1 M(1) and applying CNOT(0,2). This way you are sure that the measurement is moved and sabre is doing something.
The test_sabre_final_measurements I would remove, instead, and add the final measurements testing to test_sabre_random_circuits.

@pytest.mark.parametrize("gates", [10, 40])
@pytest.mark.parametrize("look", [0, 5])
@pytest.mark.parametrize("decay", [0.5, 1.0])
@pytest.mark.parametrize("placer", [Trivial, Random])
@pytest.mark.parametrize("connectivity", [star_connectivity(), grid_connectivity()])
def test_sabre_random_circuits(gates, look, decay, placer, connectivity):
    placer = placer(connectivity=connectivity)
    layout_circ = Circuit(5)
    initial_layout = placer(layout_circ)
    router = Sabre(connectivity=connectivity, lookahead=look, decay_lookahead=decay)
    circuit = generate_random_circuit(nqubits=5, ngates=gates)
    measurement = gates.M(np.random.choice(range(5), size=3, replace=False))
    circuit.add(measurement)
    transpiled_circuit, final_qubit_map = router(circuit, initial_layout)
    assert router.added_swaps >= 0
    assert_connectivity(connectivity, transpiled_circuit)
    assert_placement(transpiled_circuit, final_qubit_map)
    assert gates + router.added_swaps == transpiled_circuit.ngates
    assert_circuit_equivalence(
        original_circuit=circuit,
        transpiled_circuit=transpiled_circuit,
        final_map=final_qubit_map,
        initial_map=initial_layout,
    )
    circuit_result = routed_circ.execute(nshots=100)
    assert circuit_result.frequencies() == measurement.result.frequencies()
    assert routed_circ.queue[-1].result is measurement.result

@BrunoLiegiBastonLiegi
Copy link
Contributor

In test_intermediate_measurements I tried moving the measurement to qubit 1, i.e. the one that gets swapped by the router, and it's moved at the end of the queue after routing.

# circ.queue
[<qibo.gates.gates.H object at 0x7f0f2beffb90>, <qibo.gates.measurements.M object at 0x7f0f2be5dc50>, <qibo.gates.gates.CNOT object at 0x7f0f2beffbd0>]

# routed_circ.queue
[<qibo.gates.gates.SWAP object at 0x7f0f285287d0>, <qibo.gates.gates.H object at 0x7f0f2852b110>, <qibo.gates.gates.CNOT object at 0x7f0f2852b2d0>, <qibo.gates.measurements.M object at 0x7f0f2bef3d90>]

@Simone-Bordoni
Copy link
Contributor Author

In test_intermediate_measurements I tried moving the measurement to qubit 1, i.e. the one that gets swapped by the router, and it's moved at the end of the queue after routing.

# circ.queue
[<qibo.gates.gates.H object at 0x7f0f2beffb90>, <qibo.gates.measurements.M object at 0x7f0f2be5dc50>, <qibo.gates.gates.CNOT object at 0x7f0f2beffbd0>]

# routed_circ.queue
[<qibo.gates.gates.SWAP object at 0x7f0f285287d0>, <qibo.gates.gates.H object at 0x7f0f2852b110>, <qibo.gates.gates.CNOT object at 0x7f0f2852b2d0>, <qibo.gates.measurements.M object at 0x7f0f2bef3d90>]

Thme measurement gate commutes with the CNOT (different qubits) so the order is irrelevant.

@MatteoRobbiati MatteoRobbiati merged commit 5c4b4b2 into master Nov 22, 2023
21 checks passed
@scarrazza scarrazza deleted the sabre_mesurements branch December 4, 2023 07:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants