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

generate_cutting_experiments returns coefficients, not weights #412

Merged
merged 1 commit into from
Sep 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions circuit_knitting/cutting/cutting_experiments.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def generate_cutting_experiments(
list[tuple[float, WeightType]],
]:
r"""
Generate cutting subexperiments and their associated weights.
Generate cutting subexperiments and their associated coefficients.

If the input, ``circuits``, is a :class:`QuantumCircuit` instance, the
output subexperiments will be contained within a 1D array, and ``observables`` is
Expand All @@ -56,7 +56,7 @@ def generate_cutting_experiments(

:math:`[sample_{0}observable_{0}, \ldots, sample_{0}observable_{N}, sample_{1}observable_{0}, \ldots, sample_{M}observable_{N}]`

The weights will always be returned as a 1D array -- one weight for each unique sample.
The coefficients will always be returned as a 1D array -- one coefficient for each unique sample.

Args:
circuits: The circuit(s) to partition and separate
Expand All @@ -65,14 +65,14 @@ def generate_cutting_experiments(
to infinity, the weights will be generated rigorously rather than by sampling from
the distribution.
Returns:
A tuple containing the cutting experiments and their associated weights.
A tuple containing the cutting experiments and their associated coefficients.
If the input circuits is a :class:`QuantumCircuit` instance, the output subexperiments
will be a sequence of circuits -- one for every unique sample and observable. If the
input circuits are represented as a dictionary keyed by partition labels, the output
subexperiments will also be a dictionary keyed by partition labels and containing
the subexperiments for each partition.
The weights are always a sequence of length-2 tuples, where each tuple contains the
weight and the :class:`WeightType`. Each weight corresponds to one unique sample.
The coefficients are always a sequence of length-2 tuples, where each tuple contains the
coefficient and the :class:`WeightType`. Each coefficient corresponds to one unique sample.

Raises:
ValueError: ``num_samples`` must be at least one.
Expand Down Expand Up @@ -134,15 +134,15 @@ def generate_cutting_experiments(
# Sort samples in descending order of frequency
sorted_samples = sorted(random_samples.items(), key=lambda x: x[1][0], reverse=True)

# Generate the output experiments and weights
# Generate the output experiments and their respective coefficients
subexperiments_dict: dict[str | int, list[QuantumCircuit]] = defaultdict(list)
weights: list[tuple[float, WeightType]] = []
coefficients: list[tuple[float, WeightType]] = []
for z, (map_ids, (redundancy, weight_type)) in enumerate(sorted_samples):
actual_coeff = np.prod(
[basis.coeffs[map_id] for basis, map_id in strict_zip(bases, map_ids)]
)
sampled_coeff = (redundancy / num_samples) * (kappa * np.sign(actual_coeff))
weights.append((sampled_coeff, weight_type))
coefficients.append((sampled_coeff, weight_type))
map_ids_tmp = map_ids
for i, (subcircuit, label) in enumerate(
strict_zip(subcircuit_list, sorted(subsystem_observables.keys()))
Expand All @@ -166,7 +166,7 @@ def generate_cutting_experiments(
assert len(subexperiments_out.keys()) == 1
subexperiments_out = list(subexperiments_dict.values())[0]

return subexperiments_out, weights
return subexperiments_out, coefficients


def _get_mapping_ids_by_partition(
Expand Down
16 changes: 8 additions & 8 deletions test/cutting/test_cutting_experiments.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,19 +38,19 @@ def test_generate_cutting_experiments(self):
TwoQubitQPDGate(QPDBasis.from_gate(CXGate()), label="cut_cx"),
qargs=[0, 1],
)
comp_weights = [
comp_coeffs = [
(0.5, WeightType.EXACT),
(0.5, WeightType.EXACT),
(0.5, WeightType.EXACT),
(-0.5, WeightType.EXACT),
(0.5, WeightType.EXACT),
(-0.5, WeightType.EXACT),
]
subexperiments, weights = generate_cutting_experiments(
subexperiments, coeffs = generate_cutting_experiments(
qc, PauliList(["ZZ"]), np.inf
)
assert weights == comp_weights
assert len(weights) == len(subexperiments)
assert coeffs == comp_coeffs
assert len(coeffs) == len(subexperiments)
for exp in subexperiments:
assert isinstance(exp, QuantumCircuit)

Expand All @@ -68,19 +68,19 @@ def test_generate_cutting_experiments(self):
),
qargs=[1],
)
comp_weights = [
comp_coeffs = [
(0.5, WeightType.EXACT),
(0.5, WeightType.EXACT),
(0.5, WeightType.EXACT),
(-0.5, WeightType.EXACT),
(0.5, WeightType.EXACT),
(-0.5, WeightType.EXACT),
]
subexperiments, weights = generate_cutting_experiments(
subexperiments, coeffs = generate_cutting_experiments(
{"A": qc}, {"A": PauliList(["ZY"])}, np.inf
)
assert weights == comp_weights
assert len(weights) == len(subexperiments["A"])
assert coeffs == comp_coeffs
assert len(coeffs) == len(subexperiments["A"])
for circ in subexperiments["A"]:
assert isinstance(circ, QuantumCircuit)

Expand Down