Skip to content

Commit

Permalink
Update transpile()'s default opt level to match
Browse files Browse the repository at this point in the history
This commit updates the transpile() function's optimization_level argument
default value to match generate_preset_pass_manager's new default to use 2
instead of 1. This is arguably a breaking API change, but since the
semantics are equivalent with two minor edge cases with implicit behavior
that were a side effect of the level 1 preset pass manager's construction
(which are documented in the release notes) we're ok making it in this
case. Some tests which we're relying on the implicit behavior of
optimization level 1 are updated to explicitly set the optimization
level argument which will retain this behavior.
  • Loading branch information
mtreinish committed Apr 30, 2024
1 parent 439a390 commit 34e9ee4
Show file tree
Hide file tree
Showing 9 changed files with 55 additions and 14 deletions.
4 changes: 2 additions & 2 deletions qiskit/compiler/transpiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ def transpile( # pylint: disable=too-many-return-statements
* 2: heavy optimization
* 3: even heavier optimization
If ``None``, level 1 will be chosen as default.
If ``None``, level 2 will be chosen as default.
callback: A callback function that will be called after each
pass execution. The function will be called with 5 keyword
arguments,
Expand Down Expand Up @@ -315,7 +315,7 @@ def callback_func(**kwargs):
if optimization_level is None:
# Take optimization level from the configuration or 1 as default.
config = user_config.get_config()
optimization_level = config.get("transpile_optimization_level", 1)
optimization_level = config.get("transpile_optimization_level", 2)

if backend is not None and getattr(backend, "version", 0) <= 1:
# This is a temporary conversion step to allow for a smoother transition
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,28 @@ features_transpiler:
generate_preset_pass_manager(backend.Target)
will construct a default pass manager for the 100 qubit :class`.GenericBackendV2` instance.
upgrade_transpiler:
- |
The default ``optimization_level`` used by the :func:`.transpile` function when one is not
specified has been changed to level 2. This makes it consistent with the default used
by :func:`.generate_preset_pass_manager` which is used internally by :func:`.transpile`. If
you were previously relying on the implicit default of level 1, you can simply set
the argument ``optimization_level=1`` when you call :func:`.transpile`. There isn't an API
change though because fundamentally level 2 and level 1 have the same semantics. Similarly you
can change the default back in your local environment by using a user config file and setting
the ``transpile_optimization_level`` field to 1.
The only potential issue is that if you were relying on an implicit trivial layout (where qubit 0
in the circuit passed to :func:`.transpile` is mapped to qubit 0 on the target backend/coupling,
1->1, 2->2, etc.) without specifying ``optimization_level=1``, ``layout_method="trivial"``, or
explicitly setting ``initial_layout`` when calling :func:`.transpile`. This behavior was a side
effect of the preset pass manager construction in optimization level 1 and is not mirrored in
level 2. If you need this behavior you can use any of the three options list previously to make
this behavior explicit.
Similarly if you were targeting a discrete basis gate set you may encounter an issue using the
new default with optimization level 2 (or 3) as the additional optimization passes that run in
level 2 and 3 don't work in all cases with a discrete basis. You can explicitly set
``optimization_level=1`` manually in this case. In general the transpiler does not currently
fully support discrete basis sets and if you're relying on this you should likely construct a
pass manager manually to build a compilation pipeline that will work with your target.
2 changes: 1 addition & 1 deletion test/python/circuit/library/test_qft.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ def test_qft_num_gates(self, num_qubits, approximation_degree, insert_barriers):
qft = QFT(
num_qubits, approximation_degree=approximation_degree, insert_barriers=insert_barriers
)
ops = transpile(qft, basis_gates=basis_gates).count_ops()
ops = transpile(qft, basis_gates=basis_gates, optimization_level=1).count_ops()

with self.subTest(msg="assert H count"):
self.assertEqual(ops["h"], num_qubits)
Expand Down
14 changes: 12 additions & 2 deletions test/python/compiler/test_transpiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -517,11 +517,21 @@ def test_transpile_bell_discrete_basis(self):

# Try with the initial layout in both directions to ensure we're dealing with the basis
# having only a single direction.

# Use optimization level=1 because the synthesis that runs as part of optimization at
# higher optimization levels will create intermediate gates that the transpiler currently
# lacks logic to translate to a discrete basis.
self.assertIsInstance(
transpile(qc, target=target, initial_layout=[0, 1], seed_transpiler=42), QuantumCircuit
transpile(
qc, target=target, initial_layout=[0, 1], seed_transpiler=42, optimization_level=1
),
QuantumCircuit,
)
self.assertIsInstance(
transpile(qc, target=target, initial_layout=[1, 0], seed_transpiler=42), QuantumCircuit
transpile(
qc, target=target, initial_layout=[1, 0], seed_transpiler=42, optimization_level=1
),
QuantumCircuit,
)

def test_transpile_one(self):
Expand Down
2 changes: 1 addition & 1 deletion test/python/primitives/test_primitive.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ def test_with_scheduling(n):
qc = QuantumCircuit(1)
qc.x(0)
qc.add_calibration("x", qubits=(0,), schedule=custom_gate)
return transpile(qc, Fake20QV1(), scheduling_method="alap")
return transpile(qc, Fake20QV1(), scheduling_method="alap", optimization_level=1)

keys = [_circuit_key(test_with_scheduling(i)) for i in range(1, 5)]
self.assertEqual(len(keys), len(set(keys)))
Expand Down
8 changes: 4 additions & 4 deletions test/python/providers/test_backend_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ def test_transpile_respects_arg_constraints(self):
qc = QuantumCircuit(2)
qc.h(0)
qc.cx(1, 0)
tqc = transpile(qc, self.backend)
tqc = transpile(qc, self.backend, optimization_level=1)
self.assertTrue(Operator.from_circuit(tqc).equiv(qc))
# Below is done to check we're decomposing cx(1, 0) with extra
# rotations to correct for direction. However because of fp
Expand All @@ -163,7 +163,7 @@ def test_transpile_respects_arg_constraints(self):
qc = QuantumCircuit(2)
qc.h(0)
qc.ecr(0, 1)
tqc = transpile(qc, self.backend)
tqc = transpile(qc, self.backend, optimization_level=1)
self.assertTrue(Operator.from_circuit(tqc).equiv(qc))
self.assertEqual(tqc.count_ops(), {"ecr": 1, "u": 4})
self.assertMatchesTargetConstraints(tqc, self.backend.target)
Expand All @@ -173,7 +173,7 @@ def test_transpile_relies_on_gate_direction(self):
qc = QuantumCircuit(2)
qc.h(0)
qc.ecr(0, 1)
tqc = transpile(qc, self.backend)
tqc = transpile(qc, self.backend, optimization_level=1)
expected = QuantumCircuit(2)
expected.u(0, 0, -math.pi, 0)
expected.u(math.pi / 2, 0, 0, 1)
Expand All @@ -191,7 +191,7 @@ def test_transpile_mumbai_target(self):
qc.h(0)
qc.cx(1, 0)
qc.measure_all()
tqc = transpile(qc, backend)
tqc = transpile(qc, backend, optimization_level=1)
qr = QuantumRegister(27, "q")
cr = ClassicalRegister(2, "meas")
expected = QuantumCircuit(qr, cr, global_phase=math.pi / 4)
Expand Down
8 changes: 5 additions & 3 deletions test/python/pulse/test_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -764,7 +764,9 @@ def get_sched(qubit_idx: [int], backend):
qc = circuit.QuantumCircuit(2)
for idx in qubit_idx:
qc.append(circuit.library.U2Gate(0, pi / 2), [idx])
return compiler.schedule(compiler.transpile(qc, backend=backend), backend)
return compiler.schedule(
compiler.transpile(qc, backend=backend, optimization_level=1), backend
)

with pulse.build(self.backend) as schedule:
with pulse.align_sequential():
Expand All @@ -784,7 +786,7 @@ def get_sched(qubit_idx: [int], backend):
# prepare and schedule circuits that will be used.
single_u2_qc = circuit.QuantumCircuit(2)
single_u2_qc.append(circuit.library.U2Gate(0, pi / 2), [1])
single_u2_qc = compiler.transpile(single_u2_qc, self.backend)
single_u2_qc = compiler.transpile(single_u2_qc, self.backend, optimization_level=1)
single_u2_sched = compiler.schedule(single_u2_qc, self.backend)

# sequential context
Expand All @@ -809,7 +811,7 @@ def get_sched(qubit_idx: [int], backend):
triple_u2_qc.append(circuit.library.U2Gate(0, pi / 2), [0])
triple_u2_qc.append(circuit.library.U2Gate(0, pi / 2), [1])
triple_u2_qc.append(circuit.library.U2Gate(0, pi / 2), [0])
triple_u2_qc = compiler.transpile(triple_u2_qc, self.backend)
triple_u2_qc = compiler.transpile(triple_u2_qc, self.backend, optimization_level=1)
align_left_reference = compiler.schedule(triple_u2_qc, self.backend, method="alap")

# measurement
Expand Down
1 change: 1 addition & 0 deletions test/python/transpiler/test_basis_translator.py
Original file line number Diff line number Diff line change
Expand Up @@ -1055,6 +1055,7 @@ def test_skip_target_basis_equivalences_1(self):
circ,
basis_gates=["id", "rz", "sx", "x", "cx"],
seed_transpiler=42,
optimization_level=1,
)
self.assertEqual(circ_transpiled.count_ops(), {"cx": 91, "rz": 66, "sx": 22})

Expand Down
5 changes: 4 additions & 1 deletion test/python/transpiler/test_sabre_layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,9 @@ def test_layout_with_classical_bits(self):
rz(0) q4835[1];
"""
)
res = transpile(qc, Fake27QPulseV1(), layout_method="sabre", seed_transpiler=1234)
res = transpile(
qc, Fake27QPulseV1(), layout_method="sabre", seed_transpiler=1234, optimization_level=1
)
self.assertIsInstance(res, QuantumCircuit)
layout = res._layout.initial_layout
self.assertEqual(
Expand Down Expand Up @@ -250,6 +252,7 @@ def test_layout_many_search_trials(self):
layout_method="sabre",
routing_method="stochastic",
seed_transpiler=12345,
optimization_level=1,
)
self.assertIsInstance(res, QuantumCircuit)
layout = res._layout.initial_layout
Expand Down

0 comments on commit 34e9ee4

Please sign in to comment.