"""Standard naming conventions for physical parameters and modes in quantum circuit designs."""
from typing import Literal, Tuple, Union
# Standard mode types
RESONATOR = "resonator"
QUBIT = "qubit"
CAVITY = "cavity"
COUPLER = "coupler"
# Parameter types
FREQ: Literal["freq"] = "freq"
KAPPA: Literal["kappa"] = "kappa"
CHARGE_LINE_LIMITED_T1: Literal["charge_line_limited_t1"] = "charge_line_limited_t1"
NONLIN: Literal["nonlinearity"] = "nonlinearity"
CAPACITANCE = "capacitance"
""" dict: Maps branch to capacitance matrix elements in capacitance matrix simulation.
Capacitance matrix elements are in femto Farads (fF).
Format: (capacitance_name, capacitance_name): value
Example: {
('comb_NAME_QB1', 'comb_NAME_QB1'): 100,
('comb_NAME_QB1', 'comb_NAME_QB2'): 5,
}
"""
ITERATION = "ITERATION"
"""Special parameter identifier used for tracking optimization iterations."""
Mode = str
"""Type representing a unique mode name in the format 'modetype_identifier'.
The mode name must be unique within a design and follows a standardized format
of lowercase mode type, optionally followed by an underscore and an identifier.
Examples:
>>> "qubit" # A single qubit without an identifier
>>> "qubit_1" # First qubit in a multi-qubit system
>>> "resonator_a" # A resonator with string identifier 'a'
"""
Parameter = str
"""Type representing a parameter name, formed by concatenating a unique mode name with a parameter type.
The parameter name uniquely identifies a physical quantity associated with
one or more modes in the system.
Examples:
>>> "qubit_freq" # Frequency of a qubit
>>> "qubit_1_kappa" # Decay rate of qubit 1
>>> "qubit_1_to_resonator_1_nonlin" # Cross-Kerr interaction
"""
[docs]
def mode(
mode_type: str,
identifier: Union[int, str, None] = None,
) -> Mode:
"""
Construct a standardized mode name from a mode type and optional identifier.
Creates a unique mode name by combining the mode type with an optional identifier. The resulting
name follows the convention 'modetype_identifier' and must be unique within a design.
Args:
mode_type (str): The type of mode (e.g., "qubit", "resonator").
Must not contain underscores or the string "_to_".
identifier (int, str, None): Optional identifier for the mode.
Must not contain underscores or the string "_to_". If None, only the mode_type is used.
Returns:
Mode: A standardized mode name in the format 'modetype_identifier'.
Raises:
AssertionError: If mode_type or identifier contains forbidden characters.
Examples:
>>> mode("qubit", 1)
'qubit_1'
>>> mode("resonator", "a")
'resonator_a'
>>> mode("cavity")
'cavity'
"""
assert "_" not in mode_type, "mode_type cannot contain underscores"
assert (
"_to_" not in mode_type
), "mode_type cannot contain the string '_to_', since it is a keyword for nonlinear parameters"
assert identifier is None or "_" not in str(
identifier
), "identifier cannot contain underscores"
mode_name = mode_type
if identifier is not None:
assert (
isinstance(identifier, int) or "_to_" not in identifier
), "identifier cannot contain the string '_to_', since it is a keyword for nonlinear parameters"
mode_name = f"{mode_name}_{identifier}"
assert (
":" not in mode_name
), "Qiskit parsing does not allow mode_name to contain the character ':'"
assert (
"-" not in mode_name
), "Qiskit parsing does not allow mode_name to contain the character '-'"
return mode_name
[docs]
def param(
mode_instance: Mode,
param_type: Literal["freq", "kappa", "charge_line_limited_t1"],
) -> Parameter:
"""
Construct a parameter name from a mode and parameter type.
Creates a parameter name by concatenating the mode name with the parameter type.
Used for parameters associated with a single mode, such as frequency or decay rate.
Args:
mode_instance (Mode): The mode name (e.g., "qubit_1").
param_type (Literal): The type of parameter, must be one of:
- "freq": Frequency
- "kappa": Decay rate/linewidth
- "charge_line_limited_t1": T1 limited by charge line
Returns:
Parameter: A parameter name in the format 'mode_paramtype'.
Raises:
AssertionError: If param_type is not one of the allowed values.
Examples:
>>> param("qubit_1", "freq")
'qubit_1_freq'
>>> param("resonator_a", "kappa")
'resonator_a_kappa'
"""
assert param_type in [
"freq",
"kappa",
"charge_line_limited_t1",
], "param_type must be 'freq', 'kappa' or 'charge_line_limited_t1'"
return f"{mode_instance}_{param_type}"
[docs]
def param_nonlin(mode_1: Mode, mode_2: Mode) -> Parameter:
"""
Construct a nonlinear parameter name from two modes.
Creates a parameter name for nonlinear interactions between two modes,
such as cross-Kerr coupling or anharmonicity (self-Kerr). The modes are
sorted alphabetically to ensure consistency regardless of argument order.
Args:
mode_1 (Mode): First mode name.
mode_2 (Mode): Second mode name.
Returns:
Parameter: A nonlinearity parameter name in the format 'mode1_to_mode2_nonlin'.
Note:
If mode_1 == mode_2, the returned parameter represents the anharmonicity
(self-Kerr) of the mode.
Examples:
>>> param_nonlin("qubit_1", "qubit_2")
'qubit_1_to_qubit_2_nonlin'
>>> param_nonlin("qubit_2", "qubit_1") # Order is normalized
'qubit_1_to_qubit_2_nonlin'
>>> param_nonlin("qubit_1", "qubit_1") # Anharmonicity
'qubit_1_to_qubit_1_nonlin'
"""
modes = [mode_1, mode_2]
modes.sort()
return f"{modes[0]}_to_{modes[1]}_{'nonlin'}"
[docs]
def param_capacitance(capacitance_name_1: str, capacitance_name_2: str) -> Parameter:
"""
Construct a parameter name for capacitance matrix elements.
Creates a parameter name for capacitance between two islands or components
in the system. The capacitance names are sorted alphabetically to ensure
consistency regardless of argument order.
Args:
capacitance_name_1 (str): First capacitance island/component name.
capacitance_name_2 (str): Second capacitance island/component name.
Returns:
Parameter: A capacitance parameter name in the format
'name1_to_name2_capacitance', with values measured in femto Farads (fF).
Examples:
>>> param_capacitance("island_1", "island_2")
'island_1_to_island_2_capacitance'
>>> param_capacitance("island_2", "island_1") # Order is normalized
'island_1_to_island_2_capacitance'
"""
capacitance_names = [capacitance_name_1, capacitance_name_2]
capacitance_names.sort()
return f"{capacitance_names[0]}_to_{capacitance_names[1]}_capacitance"
[docs]
def get_mode_from_param(parameter: Parameter) -> Mode:
"""
Extract the mode identifier from a parameter name.
Parses a parameter name to retrieve the original mode name by removing
the parameter type suffix.
Args:
parameter (Parameter): The parameter name to parse.
Returns:
Mode: The extracted mode name.
Examples:
>>> get_mode_from_param("qubit_1_freq")
'qubit_1'
>>> get_mode_from_param("resonator_a_kappa")
'resonator_a'
"""
return "_".join(parameter.split("_")[:-1])
[docs]
def get_modes_from_param_nonlin(parameter: Parameter) -> Tuple[Mode, ...]:
"""
Extract mode identifiers from a nonlinear parameter name.
Parses a nonlinearity parameter name to retrieve the original mode names
that are involved in the interaction.
Args:
parameter (Parameter): The nonlinearity parameter name to parse.
Must end with "_nonlin".
Returns:
Tuple[Mode, ...]: A tuple containing the extracted mode names.
Raises:
AssertionError: If parameter does not end with "_nonlin".
Examples:
>>> get_modes_from_param_nonlin("qubit_1_to_qubit_2_nonlin")
('qubit_1', 'qubit_2')
>>> get_modes_from_param_nonlin("qubit_1_to_qubit_1_nonlin")
('qubit_1', 'qubit_1')
"""
assert parameter.endswith("_nonlin"), "parameter must end with '_nonlin'"
return tuple(parameter.split("_nonlin")[0].split("_to_")[:2])