Skip to content

Commit

Permalink
removed more deprecated backend calls, passed linting checks
Browse files Browse the repository at this point in the history
  • Loading branch information
nbronn committed Aug 9, 2024
1 parent c0c1934 commit cf35360
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 360 deletions.
18 changes: 9 additions & 9 deletions qiskit_research/utils/convenience.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from qiskit.circuit import QuantumCircuit
from qiskit.circuit import Gate
from qiskit.circuit.library import XGate
from qiskit.providers.backend import Backend
from qiskit.providers import Backend
from qiskit.transpiler import PassManager, Target
from qiskit.transpiler.passes.scheduling import ALAPScheduleAnalysis
from qiskit.transpiler.passes.scheduling.scheduling.base_scheduler import BaseScheduler
Expand Down Expand Up @@ -47,12 +47,12 @@ def add_dynamical_decoupling(
"""Add dynamical decoupling sequences and calibrations to circuits.
Adds dynamical decoupling sequences and the calibrations necessary
to run them on an IBM backend.
to run them on an IBM backend target.
Args:
circuits (Union[QuantumCircuit, List[QuantumCircuit], List[List[QuantumCircuit]]]):
input QuantumCircuit or sequences thereof.
backend (Backend): Backend to run on; gate timing is required for this method.
target (Target): Backend to run on; gate timing is required for this method.
dd_str (str): String describing DD sequence to use.
scheduler (BaseScheduler, optional): Scheduler, defaults to ALAPScheduleAnalysis.
add_pulse_cals (bool, optional): Add Pulse calibrations for non-basis
Expand Down Expand Up @@ -168,7 +168,7 @@ def add_pauli_twirls(
@overload
def scale_cr_pulses(
circuits: List[QuantumCircuit],
backend: Backend,
target: Target,
unroll_rzx_to_ecr: Optional[bool] = True,
force_zz_matches: Optional[bool] = True,
param_bind: Optional[dict] = None,
Expand All @@ -178,7 +178,7 @@ def scale_cr_pulses(
@overload
def scale_cr_pulses(
circuits: QuantumCircuit,
backend: Backend,
target: Target,
unroll_rzx_to_ecr: Optional[bool] = True,
force_zz_matches: Optional[bool] = True,
param_bind: Optional[dict] = None,
Expand All @@ -187,7 +187,7 @@ def scale_cr_pulses(

def scale_cr_pulses(
circuits,
backend,
target,
unroll_rzx_to_ecr: Optional[bool] = True,
force_zz_matches: Optional[bool] = True,
param_bind: Optional[dict] = None,
Expand All @@ -203,7 +203,7 @@ def scale_cr_pulses(
pass_manager = PassManager(
list(
cr_scaling_passes(
backend,
target,
templates,
unroll_rzx_to_ecr=unroll_rzx_to_ecr,
force_zz_matches=force_zz_matches,
Expand All @@ -216,15 +216,15 @@ def scale_cr_pulses(

def attach_cr_pulses(
circuits: Union[QuantumCircuit, List[QuantumCircuit]],
backend: Backend,
target: Target,
param_bind: dict,
) -> Union[QuantumCircuit, List[QuantumCircuit]]:
"""
Scale circuits using Pulse scaling technique from
http://arxiv.org/abs/2012.11660. Binds parameters
in param_bind and attaches pulse gates.
"""
pass_manager = PassManager(list(pulse_attaching_passes(backend, param_bind)))
pass_manager = PassManager(list(pulse_attaching_passes(target, param_bind)))
return pass_manager.run(circuits)


Expand Down
186 changes: 9 additions & 177 deletions qiskit_research/utils/cost_funcs.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,26 @@

from __future__ import annotations

from typing import List, Tuple

from qiskit.circuit import QuantumCircuit
from qiskit.converters import circuit_to_dag
from qiskit.providers.backend import Backend
from qiskit.transpiler import Target
from qiskit.transpiler.passes.layout.vf2_utils import (
build_average_error_map,
build_interaction_graph,
score_layout,
)

from math import pi
import numpy as np


def avg_error_score(qc_isa: QuantumCircuit, target: Target) -> float:
"""Calculate average error score using vf2 utils
Args:
qc_isa (QuantumCircuit): transpiled circuit
target (Target): backend target
Returns:
float: average error score determined by average error map
"""
init_layout = qc_isa.layout.final_index_layout()
dag = circuit_to_dag(qc_isa)

Expand All @@ -40,174 +43,3 @@ def avg_error_score(qc_isa: QuantumCircuit, target: Target) -> float:
return score_layout(
avg_error_map, layout, im_graph_node_map, reverse_im_graph_node_map, im_graph
)


def cost_func_scaled_cr(
circ: QuantumCircuit,
layouts: List[List[int]],
backend: Backend,
) -> List[Tuple[List[int], float]]:
"""
A custom cost function that includes T1 and T2 computed during idle periods,
for an already transpiled and scheduled circuit circ
Parameters:
circ (QuantumCircuit): scheduled circuit of interest
backend (IBMQBackend): An IBM Quantum backend instance
Returns:
float: error
"""
out = []
props = backend.properties()
inst_sched_map = backend.defaults().instruction_schedule_map
dt = backend.configuration().dt
num_qubits = backend.configuration().num_qubits
t1s = [props.qubit_property(qq, "T1")[0] for qq in range(num_qubits)]
t2s = [props.qubit_property(qq, "T2")[0] for qq in range(num_qubits)]

error = 0.0
fid = 1.0
touched = set()
for layout in layouts:
for item in circ.data:
if item[0].num_qubits == 2:
q0 = circ.find_bit(item[1][0]).index
q1 = circ.find_bit(item[1][1]).index
if inst_sched_map.has("cx", qubits=[q0, q1]):
basis_2q_error = props.gate_error("cx", [q0, q1])
elif inst_sched_map.has("ecr", qubits=[q0, q1]):
basis_2q_error = props.gate_error("ecr", [q0, q1])
elif inst_sched_map.has("ecr", qubits=[q1, q0]):
basis_2q_error = props.gate_error("ecr", [q1, q0])
else:
print(
f"{backend.name} missing 2Q gate between qubit pair ({q0}, {q1})"
)

if item[0].name == "cx":
fid *= 1 - basis_2q_error
touched.add(q0)
touched.add(q1)

# if it is a scaled pulse derived from cx
elif item[0].name == "rzx":
cr_error = np.abs(float(item[0].params[0]) / (pi / 2)) * basis_2q_error

# assumes control qubit is actually control for cr
echo_error = props.gate_error("x", q0)

fid *= 1 - max(cr_error, 2 * echo_error)
elif item[0].name == "secr":
cr_error = (
np.abs((float(item[0].params[0])) / (pi / 2)) * basis_2q_error
)

# assumes control qubit is actually control for cr
echo_error = props.gate_error("x", q0)

fid *= 1 - max(cr_error, echo_error)

elif item[0].name in ["sx", "x"]:
q0 = circ.find_bit(item[1][0]).index
fid *= 1 - props.gate_error(item[0].name, q0)
touched.add(q0)

# if it is a dynamical decoupling pulse
elif item[0].name in ["xp", "xm", "y", "yp", "ym"]:
q0 = circ.find_bit(item[1][0]).index
fid *= 1 - props.gate_error("x", q0)
touched.add(q0)

elif item[0].name == "measure":
q0 = circ.find_bit(item[1][0]).index
fid *= 1 - props.readout_error(q0)
touched.add(q0)

elif item[0].name == "delay":
q0 = circ.find_bit(item[1][0]).index
# Ignore delays that occur before gates
# This assumes you are in ground state and errors
# do not occur.
if q0 in touched:
time = item[0].duration * dt
fid *= 1 - idle_error(time, t1s[q0], t2s[q0])

error = 1 - fid
out.append((layout, error))
return out


def idle_error(
time: float,
t1: float,
t2: float,
) -> float:
"""Compute the approx. idle error from T1 and T2
Parameters:
time (float): Delay time in sec
t1 (float): T1 time in sec
t2, (float): T2 time in sec
Returns:
float: Idle error
"""
t2 = min(t1, t2)
rate1 = 1 / t1
rate2 = 1 / t2
p_reset = 1 - np.exp(-time * rate1)
p_z = (1 - p_reset) * (1 - np.exp(-time * (rate2 - rate1))) / 2
return p_z + p_reset


def cost_func_ecr(
circ: QuantumCircuit,
layouts: List[List[int]],
backend: Backend,
) -> List[Tuple[List[int], float]]:
"""
A custom cost function that includes ECR gates in either direction
Parameters:
circ (QuantumCircuit): circuit of interest
layouts (list of lists): List of specified layouts
backend (IBMQBackend): An IBM Quantum backend instance
Returns:
list: Tuples of layout and cost
"""
out = []
inst_sched_map = backend.defaults().instruction_schedule_map
props = backend.properties()
for layout in layouts:
error = 0.0
fid = 1.0
touched = set()
for item in circ.data:
if item[0].name == "ecr":
q0 = layout[circ.find_bit(item[1][0]).index]
q1 = layout[circ.find_bit(item[1][1]).index]
if inst_sched_map.has("ecr", [q0, q1]):
fid *= 1 - props.gate_error("ecr", [q0, q1])
elif inst_sched_map.has("ecr", [q1, q0]):
fid *= 1 - props.gate_error("ecr", [q1, q0])
else:
print(
f"{backend.name} does not support {item[0].name} \
for qubit pair ({q0}, {q1})"
)
touched.add(q0)
touched.add(q1)

elif item[0].name in ["sx", "x"]:
q0 = layout[circ.find_bit(item[1][0]).index]
fid *= 1 - props.gate_error(item[0].name, q0)
touched.add(q0)

elif item[0].name == "measure":
q0 = layout[circ.find_bit(item[1][0]).index]
fid *= 1 - props.readout_error(q0)
touched.add(q0)

error = 1 - fid
out.append((layout, error))
return out
Loading

0 comments on commit cf35360

Please sign in to comment.