Skip to content

Commit

Permalink
Rename subsystem_dims Dict to subsystem_dims_dict (qiskit-community#250)
Browse files Browse the repository at this point in the history
  • Loading branch information
to24toro authored and DanPuzzuoli committed Aug 2, 2023
1 parent cf25619 commit bafa8db
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -163,12 +163,12 @@ def parse_backend_hamiltonian_dict(
# force keys in hamiltonian['qub'] to be ints
qub_dict = {int(key): val for key, val in hamiltonian_dict["qub"].items()}

subsystem_dims = {int(qubit): qub_dict[int(qubit)] for qubit in subsystem_list}
subsystem_dims_dict = {int(qubit): qub_dict[int(qubit)] for qubit in subsystem_list}

# Parse the Hamiltonian
system = _regex_parser(
operator_str=hamiltonian_dict["h_str"],
subsystem_dims=subsystem_dims,
subsystem_dims_dict=subsystem_dims_dict,
subsystem_list=subsystem_list,
)

Expand Down Expand Up @@ -227,7 +227,12 @@ def parse_backend_hamiltonian_dict(
*sorted(zip(reduced_channels, hamiltonian_operators))
)

return static_hamiltonian, list(hamiltonian_operators), list(reduced_channels), subsystem_dims
return (
static_hamiltonian,
list(hamiltonian_operators),
list(reduced_channels),
subsystem_dims_dict,
)


def _hamiltonian_pre_parse_exceptions(hamiltonian_dict: dict):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,14 @@


def _operator_from_string(
op_label: str, subsystem_label: int, subsystem_dims: Dict[int, int]
op_label: str, subsystem_label: int, subsystem_dims_dict: Dict[int, int]
) -> np.ndarray:
r"""Generates a dense operator acting on a single subsystem, tensoring
identities for remaining subsystems.
The single system operator is specified via a string in ``op_label``,
the list of subsystems and their corresponding dimensions are specified in the
dictionary ``subsystem_dims``, with system label being the keys specified as ``int``s,
dictionary ``subsystem_dims_dict``, with system label being the keys specified as ``int``s,
and system dimensions the values also specified as ``int``s, and ``subsystem_label``
indicates which subsystem the operator specified by ``op_label`` acts on.
Expand Down Expand Up @@ -61,7 +61,7 @@ def _operator_from_string(
Args:
op_label: The string labelling the single system operator.
subsystem_label: Index of the subsystem to apply the operator.
subsystem_dims: Dictionary of subsystem labels and dimensions.
subsystem_dims_dict: Dictionary of subsystem labels and dimensions.
Returns:
np.ndarray corresponding to the specified operator.
Expand All @@ -75,12 +75,12 @@ def _operator_from_string(
if op_func is None:
raise QiskitError(f"String {op_label} does not correspond to a known operator.")

dim = subsystem_dims[subsystem_label]
dim = subsystem_dims_dict[subsystem_label]
out = qi.Operator(op_func(dim), input_dims=[dim], output_dims=[dim])

# sort subsystem labels and dimensions according to subsystem label
sorted_subsystem_keys, sorted_subsystem_dims = zip(
*sorted(zip(subsystem_dims.keys(), subsystem_dims.values()))
*sorted(zip(subsystem_dims_dict.keys(), subsystem_dims_dict.values()))
)

# get subsystem location in ordered list
Expand Down
18 changes: 10 additions & 8 deletions qiskit_dynamics/backend/backend_string_parser/regex_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,20 @@


def _regex_parser(
operator_str: List[str], subsystem_dims: Dict[int, int], subsystem_list: List[int]
operator_str: List[str], subsystem_dims_dict: Dict[int, int], subsystem_list: List[int]
) -> List[Tuple[np.array, str]]:
"""Function wrapper for regex parsing object.
Args:
operator_str: List of strings in accepted format as described in
string_model_parser.parse_hamiltonian_dict.
subsystem_dims: Dictionary mapping subsystem labels to dimensions.
subsystem_dims_dict: Dictionary mapping subsystem labels to dimensions.
subsystem_list: List of subsystems on which the operators are to be constructed.
Returns:
List of tuples containing pairs operators and their string coefficients.
"""

return _HamiltonianParser(h_str=operator_str, subsystem_dims=subsystem_dims).parse(
return _HamiltonianParser(h_str=operator_str, subsystem_dims_dict=subsystem_dims_dict).parse(
subsystem_list
)

Expand All @@ -66,15 +66,17 @@ class _HamiltonianParser:
BrkR=re.compile(r"\)"),
)

def __init__(self, h_str, subsystem_dims):
def __init__(self, h_str, subsystem_dims_dict):
"""Create new quantum operator generator
Parameters:
h_str (list): list of Hamiltonian string
subsystem_dims (dict): dimension of subsystems
subsystem_dims_dict (dict): dimension of subsystems
"""
self.h_str = h_str
self.subsystem_dims = {int(label): int(dim) for label, dim in subsystem_dims.items()}
self.subsystem_dims_dict = {
int(label): int(dim) for label, dim in subsystem_dims_dict.items()
}
self.str2qopr = {}

def parse(self, qubit_list=None):
Expand Down Expand Up @@ -194,15 +196,15 @@ def _tokenizer(self, op_str, qubit_list=None):
if qubit_list is not None and idx not in qubit_list:
return 0, None
name = p.group("opr")
opr = _operator_from_string(name, idx, self.subsystem_dims)
opr = _operator_from_string(name, idx, self.subsystem_dims_dict)
self.str2qopr[p.group()] = opr
elif key == "PrjOpr":
_key = key
_name = p.group()
if p.group() not in self.str2qopr:
idx = int(p.group("idx"))
name = "P"
opr = _operator_from_string(name, idx, self.subsystem_dims)
opr = _operator_from_string(name, idx, self.subsystem_dims_dict)
self.str2qopr[p.group()] = opr
elif key in ["Func", "Ext"]:
_name = p.group("name")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,11 +123,13 @@ def test_only_static_terms(self):
"""Test a basic system."""
ham_dict = {"h_str": ["v*np.pi*Z0"], "qub": {"0": 2}, "vars": {"v": 2.1}}

static_ham, ham_ops, channels, subsystem_dims = parse_backend_hamiltonian_dict(ham_dict)
static_ham, ham_ops, channels, subsystem_dims_dict = parse_backend_hamiltonian_dict(
ham_dict
)
self.assertAllClose(static_ham, 2.1 * np.pi * self.Z)
self.assertTrue(not ham_ops)
self.assertTrue(not channels)
self.assertTrue(subsystem_dims == {0: 2})
self.assertTrue(subsystem_dims_dict == {0: 2})

def test_simple_single_q_system(self):
"""Test a basic system."""
Expand All @@ -137,12 +139,14 @@ def test_simple_single_q_system(self):
"vars": {"v": 2.1},
}

static_ham, ham_ops, channels, subsystem_dims = parse_backend_hamiltonian_dict(ham_dict)
static_ham, ham_ops, channels, subsystem_dims_dict = parse_backend_hamiltonian_dict(
ham_dict
)

self.assertAllClose(static_ham, 2.1 * np.pi * self.Z)
self.assertAllClose(to_array(ham_ops), [0.02 * np.pi * self.X])
self.assertTrue(channels == ["d0"])
self.assertTrue(subsystem_dims == {0: 2})
self.assertTrue(subsystem_dims_dict == {0: 2})

def test_simple_single_q_system_repeat_entries(self):
"""Test merging of terms with same channel or no channel."""
Expand All @@ -152,12 +156,14 @@ def test_simple_single_q_system_repeat_entries(self):
"vars": {"v": 2.1},
}

static_ham, ham_ops, channels, subsystem_dims = parse_backend_hamiltonian_dict(ham_dict)
static_ham, ham_ops, channels, subsystem_dims_dict = parse_backend_hamiltonian_dict(
ham_dict
)

self.assertAllClose(static_ham, 2 * 2.1 * np.pi * self.Z)
self.assertAllClose(to_array(ham_ops), [2 * 0.02 * np.pi * self.X])
self.assertTrue(channels == ["d0"])
self.assertTrue(subsystem_dims == {0: 2})
self.assertTrue(subsystem_dims_dict == {0: 2})

def test_simple_single_q_system_repeat_entries_different_case(self):
"""Test merging of terms with same channel or no channel,
Expand All @@ -169,12 +175,14 @@ def test_simple_single_q_system_repeat_entries_different_case(self):
"vars": {"v": 2.1},
}

static_ham, ham_ops, channels, subsystem_dims = parse_backend_hamiltonian_dict(ham_dict)
static_ham, ham_ops, channels, subsystem_dims_dict = parse_backend_hamiltonian_dict(
ham_dict
)

self.assertAllClose(static_ham, 2 * 2.1 * np.pi * self.Z)
self.assertAllClose(to_array(ham_ops), [2 * 0.02 * np.pi * self.X])
self.assertTrue(channels == ["d0"])
self.assertTrue(subsystem_dims == {0: 2})
self.assertTrue(subsystem_dims_dict == {0: 2})

def test_simple_two_q_system(self):
"""Test a two qubit system."""
Expand All @@ -191,7 +199,9 @@ def test_simple_two_q_system(self):
"vars": {"v0": 2.1, "v1": 2.0, "j": 0.02},
}

static_ham, ham_ops, channels, subsystem_dims = parse_backend_hamiltonian_dict(ham_dict)
static_ham, ham_ops, channels, subsystem_dims_dict = parse_backend_hamiltonian_dict(
ham_dict
)

ident = np.eye(2)
self.assertAllClose(
Expand All @@ -205,7 +215,7 @@ def test_simple_two_q_system(self):
[0.02 * np.pi * np.kron(ident, self.X), 0.03 * np.pi * np.kron(self.X, ident)],
)
self.assertTrue(channels == ["d0", "d1"])
self.assertTrue(subsystem_dims == {0: 2, 1: 2})
self.assertTrue(subsystem_dims_dict == {0: 2, 1: 2})

def test_simple_two_q_system_measurement_channel(self):
"""Test a two qubit system with a measurement-labelled channel."""
Expand All @@ -222,7 +232,9 @@ def test_simple_two_q_system_measurement_channel(self):
"vars": {"v0": 2.1, "v1": 2.0, "j": 0.02},
}

static_ham, ham_ops, channels, subsystem_dims = parse_backend_hamiltonian_dict(ham_dict)
static_ham, ham_ops, channels, subsystem_dims_dict = parse_backend_hamiltonian_dict(
ham_dict
)

ident = np.eye(2)
self.assertAllClose(
Expand All @@ -236,7 +248,7 @@ def test_simple_two_q_system_measurement_channel(self):
[0.02 * np.pi * np.kron(ident, self.X), 0.03 * np.pi * np.kron(self.X, ident)],
)
self.assertTrue(channels == ["d0", "m1"])
self.assertTrue(subsystem_dims == {0: 2, 1: 2})
self.assertTrue(subsystem_dims_dict == {0: 2, 1: 2})

def test_single_oscillator_system(self):
"""Test single oscillator system."""
Expand All @@ -247,12 +259,14 @@ def test_single_oscillator_system(self):
"vars": {"v": 2.1, "alpha": -0.33, "r": 0.02},
}

static_ham, ham_ops, channels, subsystem_dims = parse_backend_hamiltonian_dict(ham_dict)
static_ham, ham_ops, channels, subsystem_dims_dict = parse_backend_hamiltonian_dict(
ham_dict
)

self.assertAllClose(static_ham, 2.1 * np.pi * self.N - 0.33 * np.pi * self.N * self.N)
self.assertAllClose(to_array(ham_ops), [0.02 * np.pi * (self.a + self.adag)])
self.assertTrue(channels == ["d0"])
self.assertTrue(subsystem_dims == {0: 4})
self.assertTrue(subsystem_dims_dict == {0: 4})

def test_two_oscillator_system(self):
"""Test a two qubit system."""
Expand All @@ -271,7 +285,9 @@ def test_two_oscillator_system(self):
"vars": {"v0": 2.1, "v1": 2.0, "alpha0": -0.33, "alpha1": -0.33, "j": 0.02},
}

static_ham, ham_ops, channels, subsystem_dims = parse_backend_hamiltonian_dict(ham_dict)
static_ham, ham_ops, channels, subsystem_dims_dict = parse_backend_hamiltonian_dict(
ham_dict
)

ident = np.eye(4)

Expand All @@ -291,7 +307,7 @@ def test_two_oscillator_system(self):
],
)
self.assertTrue(channels == ["d0", "d1"])
self.assertTrue(subsystem_dims == {0: 4, 1: 4})
self.assertTrue(subsystem_dims_dict == {0: 4, 1: 4})

def test_single_q_high_dim(self):
"""Test single q system but higher dim."""
Expand All @@ -301,12 +317,14 @@ def test_single_q_high_dim(self):
"vars": {"v": 2.1},
}

static_ham, ham_ops, channels, subsystem_dims = parse_backend_hamiltonian_dict(ham_dict)
static_ham, ham_ops, channels, subsystem_dims_dict = parse_backend_hamiltonian_dict(
ham_dict
)

self.assertAllClose(static_ham, 2.1 * np.pi * (np.eye(4) - 2 * self.N))
self.assertAllClose(to_array(ham_ops), [0.02 * np.pi * (self.a + self.adag)])
self.assertTrue(channels == ["d0"])
self.assertTrue(subsystem_dims == {0: 4})
self.assertTrue(subsystem_dims_dict == {0: 4})

def test_dagger(self):
"""Test correct parsing of dagger."""
Expand Down Expand Up @@ -397,13 +415,13 @@ def test_5q_hamiltonian_reduced(self):
)
channels_expected = ["d0", "d1", "u0", "u1", "u2"]

static_ham, ham_ops, channels, subsystem_dims = parse_backend_hamiltonian_dict(
static_ham, ham_ops, channels, subsystem_dims_dict = parse_backend_hamiltonian_dict(
ham_dict, subsystem_list=[0, 1]
)
self.assertAllClose(static_ham, static_ham_expected)
self.assertAllClose(ham_ops, ham_ops_expected)
self.assertTrue(channels == channels_expected)
self.assertTrue(subsystem_dims == {0: 4, 1: 4})
self.assertTrue(subsystem_dims_dict == {0: 4, 1: 4})

# test case for subsystems [3, 4]

Expand All @@ -427,10 +445,10 @@ def test_5q_hamiltonian_reduced(self):
)
channels_expected = ["d3", "d4", "u5", "u6", "u7"]

static_ham, ham_ops, channels, subsystem_dims = parse_backend_hamiltonian_dict(
static_ham, ham_ops, channels, subsystem_dims_dict = parse_backend_hamiltonian_dict(
ham_dict, subsystem_list=[3, 4]
)
self.assertAllClose(static_ham, static_ham_expected)
self.assertAllClose(ham_ops, ham_ops_expected)
self.assertTrue(channels == channels_expected)
self.assertTrue(subsystem_dims == {3: 4, 4: 4})
self.assertTrue(subsystem_dims_dict == {3: 4, 4: 4})

0 comments on commit bafa8db

Please sign in to comment.