cirq-core 1.1.0.dev20221220224914__py3-none-any.whl → 1.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cirq/__init__.py +8 -0
- cirq/_compat.py +29 -4
- cirq/_compat_test.py +24 -26
- cirq/_version.py +32 -1
- cirq/_version_test.py +1 -1
- cirq/circuits/_block_diagram_drawer_test.py +4 -3
- cirq/circuits/circuit.py +109 -63
- cirq/circuits/circuit_operation.py +2 -3
- cirq/circuits/circuit_operation_test.py +4 -4
- cirq/circuits/circuit_test.py +11 -0
- cirq/circuits/frozen_circuit.py +13 -1
- cirq/circuits/frozen_circuit_test.py +5 -1
- cirq/circuits/moment.py +39 -14
- cirq/circuits/moment_test.py +7 -0
- cirq/circuits/text_diagram_drawer.py +1 -1
- cirq/circuits/text_diagram_drawer_test.py +3 -7
- cirq/contrib/acquaintance/bipartite.py +1 -1
- cirq/contrib/acquaintance/devices.py +2 -2
- cirq/contrib/acquaintance/executor.py +5 -2
- cirq/contrib/acquaintance/gates.py +3 -2
- cirq/contrib/acquaintance/permutation.py +13 -2
- cirq/contrib/acquaintance/testing.py +3 -5
- cirq/contrib/paulistring/recombine.py +3 -6
- cirq/contrib/qasm_import/_parser.py +17 -21
- cirq/contrib/qasm_import/_parser_test.py +30 -45
- cirq/contrib/qcircuit/qcircuit_test.py +3 -7
- cirq/contrib/quantum_volume/quantum_volume.py +3 -3
- cirq/contrib/quimb/mps_simulator.py +1 -1
- cirq/contrib/quimb/state_vector.py +2 -0
- cirq/contrib/quirk/quirk_gate.py +1 -0
- cirq/contrib/svg/svg.py +4 -7
- cirq/contrib/svg/svg_test.py +29 -1
- cirq/devices/grid_qubit.py +26 -28
- cirq/devices/grid_qubit_test.py +21 -5
- cirq/devices/line_qubit.py +10 -12
- cirq/devices/line_qubit_test.py +9 -2
- cirq/devices/named_topologies.py +1 -1
- cirq/devices/noise_model.py +4 -1
- cirq/devices/superconducting_qubits_noise_properties.py +1 -3
- cirq/experiments/n_qubit_tomography.py +1 -1
- cirq/experiments/qubit_characterizations.py +2 -2
- cirq/experiments/single_qubit_readout_calibration.py +1 -1
- cirq/experiments/t2_decay_experiment.py +1 -1
- cirq/experiments/xeb_simulation_test.py +2 -2
- cirq/interop/quirk/cells/testing.py +1 -1
- cirq/json_resolver_cache.py +1 -0
- cirq/linalg/__init__.py +2 -0
- cirq/linalg/decompositions_test.py +4 -4
- cirq/linalg/diagonalize_test.py +5 -6
- cirq/linalg/transformations.py +72 -9
- cirq/linalg/transformations_test.py +23 -7
- cirq/ops/__init__.py +4 -0
- cirq/ops/arithmetic_operation.py +4 -6
- cirq/ops/classically_controlled_operation.py +10 -3
- cirq/ops/clifford_gate.py +1 -7
- cirq/ops/common_channels.py +21 -15
- cirq/ops/common_gate_families.py +2 -3
- cirq/ops/common_gates.py +48 -11
- cirq/ops/common_gates_test.py +4 -0
- cirq/ops/controlled_gate.py +44 -18
- cirq/ops/controlled_operation.py +13 -5
- cirq/ops/dense_pauli_string.py +14 -19
- cirq/ops/diagonal_gate.py +3 -4
- cirq/ops/eigen_gate.py +8 -10
- cirq/ops/eigen_gate_test.py +6 -0
- cirq/ops/gate_operation.py +11 -6
- cirq/ops/gate_operation_test.py +11 -2
- cirq/ops/gateset.py +2 -1
- cirq/ops/gateset_test.py +38 -5
- cirq/ops/global_phase_op.py +28 -2
- cirq/ops/global_phase_op_test.py +21 -0
- cirq/ops/identity.py +1 -1
- cirq/ops/kraus_channel_test.py +2 -2
- cirq/ops/linear_combinations.py +7 -6
- cirq/ops/linear_combinations_test.py +26 -10
- cirq/ops/matrix_gates.py +8 -4
- cirq/ops/matrix_gates_test.py +25 -3
- cirq/ops/measure_util.py +13 -5
- cirq/ops/measure_util_test.py +8 -2
- cirq/ops/measurement_gate.py +1 -1
- cirq/ops/measurement_gate_test.py +9 -4
- cirq/ops/mixed_unitary_channel_test.py +4 -4
- cirq/ops/named_qubit.py +2 -4
- cirq/ops/parity_gates.py +5 -1
- cirq/ops/parity_gates_test.py +6 -0
- cirq/ops/pauli_gates.py +9 -9
- cirq/ops/pauli_string.py +4 -2
- cirq/ops/pauli_string_raw_types.py +4 -11
- cirq/ops/pauli_string_test.py +13 -13
- cirq/ops/pauli_sum_exponential.py +6 -1
- cirq/ops/qubit_manager.py +97 -0
- cirq/ops/qubit_manager_test.py +66 -0
- cirq/ops/raw_types.py +75 -33
- cirq/ops/raw_types_test.py +34 -0
- cirq/ops/three_qubit_gates.py +16 -10
- cirq/ops/three_qubit_gates_test.py +4 -2
- cirq/ops/two_qubit_diagonal_gate.py +3 -3
- cirq/ops/wait_gate.py +1 -1
- cirq/protocols/__init__.py +1 -0
- cirq/protocols/act_on_protocol.py +3 -3
- cirq/protocols/act_on_protocol_test.py +5 -5
- cirq/protocols/apply_channel_protocol.py +9 -8
- cirq/protocols/apply_mixture_protocol.py +8 -8
- cirq/protocols/apply_mixture_protocol_test.py +1 -1
- cirq/protocols/apply_unitary_protocol.py +66 -19
- cirq/protocols/apply_unitary_protocol_test.py +50 -0
- cirq/protocols/circuit_diagram_info_protocol.py +7 -9
- cirq/protocols/decompose_protocol.py +167 -125
- cirq/protocols/decompose_protocol_test.py +132 -2
- cirq/protocols/has_stabilizer_effect_protocol.py +2 -1
- cirq/protocols/inverse_protocol.py +2 -2
- cirq/protocols/json_serialization_test.py +3 -3
- cirq/protocols/json_test_data/Linspace.json +20 -7
- cirq/protocols/json_test_data/Linspace.repr +4 -1
- cirq/protocols/json_test_data/Points.json +19 -8
- cirq/protocols/json_test_data/Points.repr +4 -1
- cirq/protocols/json_test_data/Result.repr_inward +1 -1
- cirq/protocols/json_test_data/ResultDict.repr +1 -1
- cirq/protocols/json_test_data/ResultDict.repr_inward +1 -1
- cirq/protocols/json_test_data/TrialResult.repr_inward +1 -1
- cirq/protocols/json_test_data/XPowGate.json +13 -5
- cirq/protocols/json_test_data/XPowGate.repr +1 -1
- cirq/protocols/json_test_data/ZPowGate.json +13 -5
- cirq/protocols/json_test_data/ZPowGate.repr +1 -1
- cirq/protocols/json_test_data/ZipLongest.json +19 -0
- cirq/protocols/json_test_data/ZipLongest.repr +1 -0
- cirq/protocols/json_test_data/spec.py +1 -0
- cirq/protocols/kraus_protocol.py +3 -4
- cirq/protocols/measurement_key_protocol.py +3 -1
- cirq/protocols/mixture_protocol.py +3 -2
- cirq/protocols/phase_protocol.py +3 -3
- cirq/protocols/pow_protocol.py +1 -2
- cirq/protocols/qasm.py +4 -4
- cirq/protocols/qid_shape_protocol.py +8 -8
- cirq/protocols/resolve_parameters.py +8 -3
- cirq/protocols/resolve_parameters_test.py +3 -3
- cirq/protocols/unitary_protocol.py +19 -11
- cirq/protocols/unitary_protocol_test.py +37 -0
- cirq/qis/channels.py +1 -1
- cirq/qis/clifford_tableau.py +4 -5
- cirq/qis/quantum_state_representation.py +7 -9
- cirq/qis/states.py +21 -13
- cirq/qis/states_test.py +7 -0
- cirq/sim/clifford/clifford_simulator.py +3 -3
- cirq/sim/density_matrix_simulation_state.py +2 -1
- cirq/sim/density_matrix_simulator.py +1 -1
- cirq/sim/density_matrix_simulator_test.py +9 -5
- cirq/sim/density_matrix_utils.py +7 -32
- cirq/sim/mux.py +2 -2
- cirq/sim/simulation_state.py +58 -18
- cirq/sim/simulation_state_base.py +5 -2
- cirq/sim/simulation_state_test.py +121 -9
- cirq/sim/simulation_utils.py +59 -0
- cirq/sim/simulation_utils_test.py +32 -0
- cirq/sim/simulator.py +2 -1
- cirq/sim/simulator_base_test.py +3 -3
- cirq/sim/sparse_simulator.py +1 -1
- cirq/sim/sparse_simulator_test.py +5 -5
- cirq/sim/state_vector.py +7 -36
- cirq/sim/state_vector_simulation_state.py +18 -1
- cirq/sim/state_vector_simulator.py +3 -2
- cirq/sim/state_vector_simulator_test.py +24 -2
- cirq/sim/state_vector_test.py +46 -15
- cirq/study/__init__.py +1 -0
- cirq/study/flatten_expressions.py +2 -2
- cirq/study/resolver.py +2 -0
- cirq/study/resolver_test.py +1 -1
- cirq/study/result.py +1 -1
- cirq/study/sweeps.py +103 -9
- cirq/study/sweeps_test.py +64 -0
- cirq/testing/__init__.py +4 -0
- cirq/testing/circuit_compare.py +15 -18
- cirq/testing/consistent_act_on.py +4 -4
- cirq/testing/consistent_controlled_gate_op_test.py +1 -1
- cirq/testing/consistent_decomposition.py +11 -2
- cirq/testing/consistent_decomposition_test.py +8 -1
- cirq/testing/consistent_protocols.py +2 -0
- cirq/testing/consistent_protocols_test.py +8 -4
- cirq/testing/consistent_qasm.py +8 -15
- cirq/testing/consistent_specified_has_unitary.py +1 -1
- cirq/testing/consistent_unitary.py +85 -0
- cirq/testing/consistent_unitary_test.py +96 -0
- cirq/testing/equivalent_repr_eval.py +10 -10
- cirq/testing/json.py +3 -3
- cirq/testing/logs.py +1 -1
- cirq/testing/order_tester.py +4 -5
- cirq/testing/random_circuit.py +3 -5
- cirq/testing/sample_gates.py +79 -0
- cirq/testing/sample_gates_test.py +59 -0
- cirq/transformers/__init__.py +2 -0
- cirq/transformers/analytical_decompositions/__init__.py +8 -0
- cirq/transformers/analytical_decompositions/pauli_string_decomposition.py +130 -0
- cirq/transformers/analytical_decompositions/pauli_string_decomposition_test.py +58 -0
- cirq/transformers/analytical_decompositions/quantum_shannon_decomposition.py +230 -0
- cirq/transformers/analytical_decompositions/quantum_shannon_decomposition_test.py +112 -0
- cirq/transformers/analytical_decompositions/three_qubit_decomposition_test.py +1 -3
- cirq/transformers/analytical_decompositions/two_qubit_to_fsim.py +1 -1
- cirq/transformers/expand_composite.py +1 -1
- cirq/transformers/heuristic_decompositions/gate_tabulation_math_utils.py +4 -4
- cirq/transformers/measurement_transformers.py +4 -4
- cirq/transformers/merge_single_qubit_gates.py +17 -4
- cirq/transformers/routing/route_circuit_cqc.py +2 -2
- cirq/transformers/stratify.py +125 -62
- cirq/transformers/stratify_test.py +20 -16
- cirq/transformers/transformer_api.py +1 -1
- cirq/transformers/transformer_primitives.py +3 -2
- cirq/transformers/transformer_primitives_test.py +11 -0
- cirq/value/abc_alt.py +3 -2
- cirq/value/abc_alt_test.py +1 -0
- cirq/value/classical_data.py +10 -10
- cirq/value/digits.py +2 -2
- cirq/value/linear_dict.py +18 -19
- cirq/value/product_state.py +7 -6
- cirq/value/value_equality_attr.py +2 -2
- cirq/vis/heatmap.py +1 -1
- cirq/vis/heatmap_test.py +2 -2
- cirq/work/collector.py +2 -2
- cirq/work/observable_measurement_data.py +5 -5
- cirq/work/observable_readout_calibration.py +3 -1
- cirq/work/observable_settings.py +1 -1
- cirq/work/pauli_sum_collector.py +9 -8
- cirq/work/sampler.py +2 -0
- cirq/work/zeros_sampler.py +2 -2
- {cirq_core-1.1.0.dev20221220224914.dist-info → cirq_core-1.2.0.dist-info}/METADATA +7 -15
- {cirq_core-1.1.0.dev20221220224914.dist-info → cirq_core-1.2.0.dist-info}/RECORD +228 -214
- {cirq_core-1.1.0.dev20221220224914.dist-info → cirq_core-1.2.0.dist-info}/WHEEL +1 -1
- {cirq_core-1.1.0.dev20221220224914.dist-info → cirq_core-1.2.0.dist-info}/LICENSE +0 -0
- {cirq_core-1.1.0.dev20221220224914.dist-info → cirq_core-1.2.0.dist-info}/top_level.txt +0 -0
|
@@ -33,17 +33,13 @@ def assert_has_qcircuit_diagram(actual: cirq.Circuit, desired: str, **kwargs) ->
|
|
|
33
33
|
"Circuit's qcircuit diagram differs from the desired diagram.\n"
|
|
34
34
|
'\n'
|
|
35
35
|
'Diagram of actual circuit:\n'
|
|
36
|
-
'{}\n'
|
|
36
|
+
f'{actual_diagram}\n'
|
|
37
37
|
'\n'
|
|
38
38
|
'Desired qcircuit diagram:\n'
|
|
39
|
-
'{}\n'
|
|
39
|
+
f'{desired_diagram}\n'
|
|
40
40
|
'\n'
|
|
41
41
|
'Highlighted differences:\n'
|
|
42
|
-
'{}\n'
|
|
43
|
-
actual_diagram,
|
|
44
|
-
desired_diagram,
|
|
45
|
-
ct.highlight_text_differences(actual_diagram, desired_diagram),
|
|
46
|
-
)
|
|
42
|
+
f'{ct.highlight_text_differences(actual_diagram, desired_diagram)}\n'
|
|
47
43
|
)
|
|
48
44
|
|
|
49
45
|
|
|
@@ -200,7 +200,7 @@ def compile_circuit(
|
|
|
200
200
|
*,
|
|
201
201
|
device_graph: nx.Graph,
|
|
202
202
|
routing_attempts: int,
|
|
203
|
-
compiler: Callable[[cirq.Circuit], cirq.Circuit] = None,
|
|
203
|
+
compiler: Optional[Callable[[cirq.Circuit], cirq.Circuit]] = None,
|
|
204
204
|
routing_algo_name: Optional[str] = None,
|
|
205
205
|
router: Optional[Callable[..., ccr.SwapNetwork]] = None,
|
|
206
206
|
add_readout_error_correction=False,
|
|
@@ -357,7 +357,7 @@ def execute_circuits(
|
|
|
357
357
|
samplers: List[cirq.Sampler],
|
|
358
358
|
circuits: List[Tuple[cirq.Circuit, List[int]]],
|
|
359
359
|
routing_attempts: int,
|
|
360
|
-
compiler: Callable[[cirq.Circuit], cirq.Circuit] = None,
|
|
360
|
+
compiler: Optional[Callable[[cirq.Circuit], cirq.Circuit]] = None,
|
|
361
361
|
repetitions: int = 10_000,
|
|
362
362
|
add_readout_error_correction=False,
|
|
363
363
|
) -> List[QuantumVolumeResult]:
|
|
@@ -429,7 +429,7 @@ def calculate_quantum_volume(
|
|
|
429
429
|
device_graph: nx.Graph,
|
|
430
430
|
samplers: List[cirq.Sampler],
|
|
431
431
|
random_state: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None,
|
|
432
|
-
compiler: Callable[[cirq.Circuit], cirq.Circuit] = None,
|
|
432
|
+
compiler: Optional[Callable[[cirq.Circuit], cirq.Circuit]] = None,
|
|
433
433
|
repetitions=10_000,
|
|
434
434
|
routing_attempts=30,
|
|
435
435
|
add_readout_error_correction=False,
|
|
@@ -569,7 +569,7 @@ class MPSState(SimulationState[_MPSHandler]):
|
|
|
569
569
|
simulation_options: MPSOptions = MPSOptions(),
|
|
570
570
|
grouping: Optional[Dict['cirq.Qid', int]] = None,
|
|
571
571
|
initial_state: int = 0,
|
|
572
|
-
classical_data: 'cirq.ClassicalDataStore' = None,
|
|
572
|
+
classical_data: Optional['cirq.ClassicalDataStore'] = None,
|
|
573
573
|
):
|
|
574
574
|
"""Creates and MPSState
|
|
575
575
|
|
|
@@ -177,6 +177,8 @@ def tensor_expectation_value(
|
|
|
177
177
|
if ram_gb > max_ram_gb:
|
|
178
178
|
raise MemoryError(f"We estimate that this contraction will take too much RAM! {ram_gb} GB")
|
|
179
179
|
e_val = tn.contract(inplace=True)
|
|
180
|
+
if isinstance(e_val, qtn.TensorNetwork):
|
|
181
|
+
e_val = e_val.item()
|
|
180
182
|
assert e_val.imag < tol
|
|
181
183
|
assert cast(complex, pauli_string.coefficient).imag < tol
|
|
182
184
|
return e_val.real * pauli_string.coefficient
|
cirq/contrib/quirk/quirk_gate.py
CHANGED
|
@@ -111,6 +111,7 @@ def single_qubit_matrix_gate(matrix: Optional[np.ndarray]) -> Optional[QuirkOp]:
|
|
|
111
111
|
if matrix is None or matrix.shape[0] != 2:
|
|
112
112
|
return None
|
|
113
113
|
|
|
114
|
+
# pylint: disable=consider-using-f-string
|
|
114
115
|
matrix = matrix.round(6)
|
|
115
116
|
matrix_repr = '{{%s+%si,%s+%si},{%s+%si,%s+%si}}' % (
|
|
116
117
|
np.real(matrix[0, 0]),
|
cirq/contrib/svg/svg.py
CHANGED
|
@@ -16,13 +16,10 @@ def fixup_text(text: str):
|
|
|
16
16
|
# https://github.com/quantumlib/Cirq/issues/4499
|
|
17
17
|
# TODO: Visualize Custom MatrixGate
|
|
18
18
|
return '?'
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
if '[cirq.VirtualTag()]' in text:
|
|
24
|
-
# https://github.com/quantumlib/Cirq/issues/2905
|
|
25
|
-
return text.replace('[cirq.VirtualTag()]', '')
|
|
19
|
+
# https://github.com/quantumlib/Cirq/issues/2905
|
|
20
|
+
text = text.replace('[<virtual>]', '')
|
|
21
|
+
text = text.replace('[cirq.VirtualTag()]', '')
|
|
22
|
+
text = text.replace('<', '<').replace('>', '>')
|
|
26
23
|
return text
|
|
27
24
|
|
|
28
25
|
|
cirq/contrib/svg/svg_test.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# pylint: disable=wrong-or-nonexistent-copyright-notice
|
|
2
|
-
import
|
|
2
|
+
import IPython.display
|
|
3
3
|
import numpy as np
|
|
4
|
+
import pytest
|
|
4
5
|
|
|
5
6
|
import cirq
|
|
6
7
|
from cirq.contrib.svg import circuit_to_svg
|
|
@@ -20,6 +21,7 @@ def test_svg():
|
|
|
20
21
|
cirq.MatrixGate(np.eye(2)).on(a),
|
|
21
22
|
)
|
|
22
23
|
)
|
|
24
|
+
assert '?' in svg_text
|
|
23
25
|
assert '<svg' in svg_text
|
|
24
26
|
assert '</svg>' in svg_text
|
|
25
27
|
|
|
@@ -57,3 +59,29 @@ def test_empty_moments():
|
|
|
57
59
|
svg_2 = circuit_to_svg(cirq.Circuit(cirq.Moment()))
|
|
58
60
|
assert '<svg' in svg_2
|
|
59
61
|
assert '</svg>' in svg_2
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
@pytest.mark.parametrize(
|
|
65
|
+
'symbol,svg_symbol',
|
|
66
|
+
[
|
|
67
|
+
('<a', '<a'),
|
|
68
|
+
('<=b', '<=b'),
|
|
69
|
+
('>c', '>c'),
|
|
70
|
+
('>=d', '>=d'),
|
|
71
|
+
('>e<', '>e<'),
|
|
72
|
+
('A[<virtual>]B[cirq.VirtualTag()]C>D<E', 'ABC>D<E'),
|
|
73
|
+
],
|
|
74
|
+
)
|
|
75
|
+
def test_gate_with_less_greater_str(symbol, svg_symbol):
|
|
76
|
+
class CustomGate(cirq.Gate):
|
|
77
|
+
def _num_qubits_(self) -> int:
|
|
78
|
+
return 1
|
|
79
|
+
|
|
80
|
+
def _circuit_diagram_info_(self, _) -> cirq.CircuitDiagramInfo:
|
|
81
|
+
return cirq.CircuitDiagramInfo(wire_symbols=[symbol])
|
|
82
|
+
|
|
83
|
+
circuit = cirq.Circuit(CustomGate().on(cirq.LineQubit(0)))
|
|
84
|
+
svg = circuit_to_svg(circuit)
|
|
85
|
+
|
|
86
|
+
_ = IPython.display.SVG(svg)
|
|
87
|
+
assert svg_symbol in svg
|
cirq/devices/grid_qubit.py
CHANGED
|
@@ -12,10 +12,10 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
import functools
|
|
16
|
-
from typing import Any, Dict, Iterable, List, Optional, Tuple, Set, TypeVar, TYPE_CHECKING
|
|
17
|
-
|
|
18
15
|
import abc
|
|
16
|
+
import functools
|
|
17
|
+
from typing import Any, Dict, Iterable, List, Optional, Tuple, Set, TYPE_CHECKING, Union
|
|
18
|
+
from typing_extensions import Self
|
|
19
19
|
|
|
20
20
|
import numpy as np
|
|
21
21
|
|
|
@@ -24,10 +24,8 @@ from cirq import _compat, ops, protocols
|
|
|
24
24
|
if TYPE_CHECKING:
|
|
25
25
|
import cirq
|
|
26
26
|
|
|
27
|
-
TSelf = TypeVar('TSelf', bound='_BaseGridQid')
|
|
28
|
-
|
|
29
27
|
|
|
30
|
-
@functools.total_ordering
|
|
28
|
+
@functools.total_ordering
|
|
31
29
|
class _BaseGridQid(ops.Qid):
|
|
32
30
|
"""The Base class for `GridQid` and `GridQubit`."""
|
|
33
31
|
|
|
@@ -47,13 +45,13 @@ class _BaseGridQid(ops.Qid):
|
|
|
47
45
|
return self._col
|
|
48
46
|
|
|
49
47
|
def with_dimension(self, dimension: int) -> 'GridQid':
|
|
50
|
-
return GridQid(self.
|
|
48
|
+
return GridQid(self._row, self._col, dimension=dimension)
|
|
51
49
|
|
|
52
50
|
def is_adjacent(self, other: 'cirq.Qid') -> bool:
|
|
53
51
|
"""Determines if two qubits are adjacent qubits."""
|
|
54
52
|
return (
|
|
55
53
|
isinstance(other, GridQubit)
|
|
56
|
-
and abs(self.
|
|
54
|
+
and abs(self._row - other._row) + abs(self._col - other._col) == 1
|
|
57
55
|
)
|
|
58
56
|
|
|
59
57
|
def neighbors(self, qids: Optional[Iterable[ops.Qid]] = None) -> Set['_BaseGridQid']:
|
|
@@ -69,20 +67,20 @@ class _BaseGridQid(ops.Qid):
|
|
|
69
67
|
return neighbors
|
|
70
68
|
|
|
71
69
|
@abc.abstractmethod
|
|
72
|
-
def _with_row_col(self
|
|
70
|
+
def _with_row_col(self, row: int, col: int) -> Self:
|
|
73
71
|
"""Returns a qid with the same type but a different coordinate."""
|
|
74
72
|
|
|
75
73
|
def __complex__(self) -> complex:
|
|
76
|
-
return self.
|
|
74
|
+
return self._col + 1j * self._row
|
|
77
75
|
|
|
78
|
-
def __add__(self
|
|
76
|
+
def __add__(self, other: Union[Tuple[int, int], Self]) -> Self:
|
|
79
77
|
if isinstance(other, _BaseGridQid):
|
|
80
78
|
if self.dimension != other.dimension:
|
|
81
79
|
raise TypeError(
|
|
82
80
|
"Can only add GridQids with identical dimension. "
|
|
83
81
|
f"Got {self.dimension} and {other.dimension}"
|
|
84
82
|
)
|
|
85
|
-
return self._with_row_col(row=self.
|
|
83
|
+
return self._with_row_col(row=self._row + other._row, col=self._col + other._col)
|
|
86
84
|
if not (
|
|
87
85
|
isinstance(other, (tuple, np.ndarray))
|
|
88
86
|
and len(other) == 2
|
|
@@ -92,16 +90,16 @@ class _BaseGridQid(ops.Qid):
|
|
|
92
90
|
'Can only add integer tuples of length 2 to '
|
|
93
91
|
f'{type(self).__name__}. Instead was {other}'
|
|
94
92
|
)
|
|
95
|
-
return self._with_row_col(row=self.
|
|
93
|
+
return self._with_row_col(row=self._row + other[0], col=self._col + other[1])
|
|
96
94
|
|
|
97
|
-
def __sub__(self
|
|
95
|
+
def __sub__(self, other: Union[Tuple[int, int], Self]) -> Self:
|
|
98
96
|
if isinstance(other, _BaseGridQid):
|
|
99
97
|
if self.dimension != other.dimension:
|
|
100
98
|
raise TypeError(
|
|
101
99
|
"Can only subtract GridQids with identical dimension. "
|
|
102
100
|
f"Got {self.dimension} and {other.dimension}"
|
|
103
101
|
)
|
|
104
|
-
return self._with_row_col(row=self.
|
|
102
|
+
return self._with_row_col(row=self._row - other._row, col=self._col - other._col)
|
|
105
103
|
if not (
|
|
106
104
|
isinstance(other, (tuple, np.ndarray))
|
|
107
105
|
and len(other) == 2
|
|
@@ -111,16 +109,16 @@ class _BaseGridQid(ops.Qid):
|
|
|
111
109
|
"Can only subtract integer tuples of length 2 to "
|
|
112
110
|
f"{type(self).__name__}. Instead was {other}"
|
|
113
111
|
)
|
|
114
|
-
return self._with_row_col(row=self.
|
|
112
|
+
return self._with_row_col(row=self._row - other[0], col=self._col - other[1])
|
|
115
113
|
|
|
116
|
-
def __radd__(self
|
|
114
|
+
def __radd__(self, other: Tuple[int, int]) -> Self:
|
|
117
115
|
return self + other
|
|
118
116
|
|
|
119
|
-
def __rsub__(self
|
|
117
|
+
def __rsub__(self, other: Tuple[int, int]) -> Self:
|
|
120
118
|
return -self + other
|
|
121
119
|
|
|
122
|
-
def __neg__(self
|
|
123
|
-
return self._with_row_col(row=-self.
|
|
120
|
+
def __neg__(self) -> Self:
|
|
121
|
+
return self._with_row_col(row=-self._row, col=-self._col)
|
|
124
122
|
|
|
125
123
|
|
|
126
124
|
class GridQid(_BaseGridQid):
|
|
@@ -257,16 +255,16 @@ class GridQid(_BaseGridQid):
|
|
|
257
255
|
return [GridQid(*c, dimension=dimension) for c in coords]
|
|
258
256
|
|
|
259
257
|
def __repr__(self) -> str:
|
|
260
|
-
return f"cirq.GridQid({self.
|
|
258
|
+
return f"cirq.GridQid({self._row}, {self._col}, dimension={self.dimension})"
|
|
261
259
|
|
|
262
260
|
def __str__(self) -> str:
|
|
263
|
-
return f"q({self.
|
|
261
|
+
return f"q({self._row}, {self._col}) (d={self.dimension})"
|
|
264
262
|
|
|
265
263
|
def _circuit_diagram_info_(
|
|
266
264
|
self, args: 'cirq.CircuitDiagramInfoArgs'
|
|
267
265
|
) -> 'cirq.CircuitDiagramInfo':
|
|
268
266
|
return protocols.CircuitDiagramInfo(
|
|
269
|
-
wire_symbols=(f"({self.
|
|
267
|
+
wire_symbols=(f"({self._row}, {self._col}) (d={self.dimension})",)
|
|
270
268
|
)
|
|
271
269
|
|
|
272
270
|
def _json_dict_(self) -> Dict[str, Any]:
|
|
@@ -307,13 +305,13 @@ class GridQubit(_BaseGridQid):
|
|
|
307
305
|
def __eq__(self, other):
|
|
308
306
|
# Explicitly implemented for performance (vs delegating to Qid).
|
|
309
307
|
if isinstance(other, GridQubit):
|
|
310
|
-
return self.
|
|
308
|
+
return self._row == other._row and self._col == other._col
|
|
311
309
|
return NotImplemented
|
|
312
310
|
|
|
313
311
|
def __ne__(self, other):
|
|
314
312
|
# Explicitly implemented for performance (vs delegating to Qid).
|
|
315
313
|
if isinstance(other, GridQubit):
|
|
316
|
-
return self.
|
|
314
|
+
return self._row != other._row or self._col != other._col
|
|
317
315
|
return NotImplemented
|
|
318
316
|
|
|
319
317
|
@property
|
|
@@ -414,15 +412,15 @@ class GridQubit(_BaseGridQid):
|
|
|
414
412
|
return [GridQubit(*c) for c in coords]
|
|
415
413
|
|
|
416
414
|
def __repr__(self) -> str:
|
|
417
|
-
return f"cirq.GridQubit({self.
|
|
415
|
+
return f"cirq.GridQubit({self._row}, {self._col})"
|
|
418
416
|
|
|
419
417
|
def __str__(self) -> str:
|
|
420
|
-
return f"q({self.
|
|
418
|
+
return f"q({self._row}, {self._col})"
|
|
421
419
|
|
|
422
420
|
def _circuit_diagram_info_(
|
|
423
421
|
self, args: 'cirq.CircuitDiagramInfoArgs'
|
|
424
422
|
) -> 'cirq.CircuitDiagramInfo':
|
|
425
|
-
return protocols.CircuitDiagramInfo(wire_symbols=(f"({self.
|
|
423
|
+
return protocols.CircuitDiagramInfo(wire_symbols=(f"({self._row}, {self._col})",))
|
|
426
424
|
|
|
427
425
|
def _json_dict_(self) -> Dict[str, Any]:
|
|
428
426
|
return protocols.obj_to_dict_helper(self, ['row', 'col'])
|
cirq/devices/grid_qubit_test.py
CHANGED
|
@@ -335,23 +335,39 @@ def test_to_json():
|
|
|
335
335
|
|
|
336
336
|
|
|
337
337
|
def test_immutable():
|
|
338
|
-
|
|
338
|
+
# Match one of two strings. The second one is message returned since python 3.11.
|
|
339
|
+
with pytest.raises(
|
|
340
|
+
AttributeError,
|
|
341
|
+
match="(can't set attribute)|(property 'col' of 'GridQubit' object has no setter)",
|
|
342
|
+
):
|
|
339
343
|
q = cirq.GridQubit(1, 2)
|
|
340
344
|
q.col = 3
|
|
341
345
|
|
|
342
|
-
with pytest.raises(
|
|
346
|
+
with pytest.raises(
|
|
347
|
+
AttributeError,
|
|
348
|
+
match="(can't set attribute)|(property 'row' of 'GridQubit' object has no setter)",
|
|
349
|
+
):
|
|
343
350
|
q = cirq.GridQubit(1, 2)
|
|
344
351
|
q.row = 3
|
|
345
352
|
|
|
346
|
-
with pytest.raises(
|
|
353
|
+
with pytest.raises(
|
|
354
|
+
AttributeError,
|
|
355
|
+
match="(can't set attribute)|(property 'col' of 'GridQid' object has no setter)",
|
|
356
|
+
):
|
|
347
357
|
q = cirq.GridQid(1, 2, dimension=3)
|
|
348
358
|
q.col = 3
|
|
349
359
|
|
|
350
|
-
with pytest.raises(
|
|
360
|
+
with pytest.raises(
|
|
361
|
+
AttributeError,
|
|
362
|
+
match="(can't set attribute)|(property 'row' of 'GridQid' object has no setter)",
|
|
363
|
+
):
|
|
351
364
|
q = cirq.GridQid(1, 2, dimension=3)
|
|
352
365
|
q.row = 3
|
|
353
366
|
|
|
354
|
-
with pytest.raises(
|
|
367
|
+
with pytest.raises(
|
|
368
|
+
AttributeError,
|
|
369
|
+
match="(can't set attribute)|(property 'dimension' of 'GridQid' object has no setter)",
|
|
370
|
+
):
|
|
355
371
|
q = cirq.GridQid(1, 2, dimension=3)
|
|
356
372
|
q.dimension = 3
|
|
357
373
|
|
cirq/devices/line_qubit.py
CHANGED
|
@@ -12,20 +12,18 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
import functools
|
|
16
|
-
from typing import Any, Dict, Iterable, List, Optional, Sequence, Set, TypeVar, TYPE_CHECKING
|
|
17
|
-
|
|
18
15
|
import abc
|
|
16
|
+
import functools
|
|
17
|
+
from typing import Any, Dict, Iterable, List, Optional, Sequence, Set, TYPE_CHECKING, Union
|
|
18
|
+
from typing_extensions import Self
|
|
19
19
|
|
|
20
20
|
from cirq import ops, protocols
|
|
21
21
|
|
|
22
22
|
if TYPE_CHECKING:
|
|
23
23
|
import cirq
|
|
24
24
|
|
|
25
|
-
TSelf = TypeVar('TSelf', bound='_BaseLineQid')
|
|
26
|
-
|
|
27
25
|
|
|
28
|
-
@functools.total_ordering
|
|
26
|
+
@functools.total_ordering
|
|
29
27
|
class _BaseLineQid(ops.Qid):
|
|
30
28
|
"""The base class for `LineQid` and `LineQubit`."""
|
|
31
29
|
|
|
@@ -66,10 +64,10 @@ class _BaseLineQid(ops.Qid):
|
|
|
66
64
|
return neighbors
|
|
67
65
|
|
|
68
66
|
@abc.abstractmethod
|
|
69
|
-
def _with_x(self
|
|
67
|
+
def _with_x(self, x: int) -> Self:
|
|
70
68
|
"""Returns a qubit with the same type but a different value of `x`."""
|
|
71
69
|
|
|
72
|
-
def __add__(self
|
|
70
|
+
def __add__(self, other: Union[int, Self]) -> Self:
|
|
73
71
|
if isinstance(other, _BaseLineQid):
|
|
74
72
|
if self.dimension != other.dimension:
|
|
75
73
|
raise TypeError(
|
|
@@ -81,7 +79,7 @@ class _BaseLineQid(ops.Qid):
|
|
|
81
79
|
raise TypeError(f"Can only add ints and {type(self).__name__}. Instead was {other}")
|
|
82
80
|
return self._with_x(self.x + other)
|
|
83
81
|
|
|
84
|
-
def __sub__(self
|
|
82
|
+
def __sub__(self, other: Union[int, Self]) -> Self:
|
|
85
83
|
if isinstance(other, _BaseLineQid):
|
|
86
84
|
if self.dimension != other.dimension:
|
|
87
85
|
raise TypeError(
|
|
@@ -95,13 +93,13 @@ class _BaseLineQid(ops.Qid):
|
|
|
95
93
|
)
|
|
96
94
|
return self._with_x(self.x - other)
|
|
97
95
|
|
|
98
|
-
def __radd__(self
|
|
96
|
+
def __radd__(self, other: int) -> Self:
|
|
99
97
|
return self + other
|
|
100
98
|
|
|
101
|
-
def __rsub__(self
|
|
99
|
+
def __rsub__(self, other: int) -> Self:
|
|
102
100
|
return -self + other
|
|
103
101
|
|
|
104
|
-
def __neg__(self
|
|
102
|
+
def __neg__(self) -> Self:
|
|
105
103
|
return self._with_x(-self.x)
|
|
106
104
|
|
|
107
105
|
def __complex__(self) -> complex:
|
cirq/devices/line_qubit_test.py
CHANGED
|
@@ -242,11 +242,18 @@ def test_for_gate():
|
|
|
242
242
|
|
|
243
243
|
|
|
244
244
|
def test_immutable():
|
|
245
|
-
|
|
245
|
+
# Match one of two strings. The second one is message returned since python 3.11.
|
|
246
|
+
with pytest.raises(
|
|
247
|
+
AttributeError,
|
|
248
|
+
match="(can't set attribute)|(property 'x' of 'LineQubit' object has no setter)",
|
|
249
|
+
):
|
|
246
250
|
q = cirq.LineQubit(5)
|
|
247
251
|
q.x = 6
|
|
248
252
|
|
|
249
|
-
with pytest.raises(
|
|
253
|
+
with pytest.raises(
|
|
254
|
+
AttributeError,
|
|
255
|
+
match="(can't set attribute)|(property 'x' of 'LineQid' object has no setter)",
|
|
256
|
+
):
|
|
250
257
|
q = cirq.LineQid(5, dimension=4)
|
|
251
258
|
q.x = 6
|
|
252
259
|
|
cirq/devices/named_topologies.py
CHANGED
|
@@ -345,7 +345,7 @@ def draw_placements(
|
|
|
345
345
|
small_graph: nx.Graph,
|
|
346
346
|
small_to_big_mappings: Sequence[Dict],
|
|
347
347
|
max_plots: int = 20,
|
|
348
|
-
axes: Sequence[plt.Axes] = None,
|
|
348
|
+
axes: Optional[Sequence[plt.Axes]] = None,
|
|
349
349
|
tilted: bool = True,
|
|
350
350
|
bad_placement_callback: Optional[Callable[[plt.Axes, int], None]] = None,
|
|
351
351
|
):
|
cirq/devices/noise_model.py
CHANGED
|
@@ -73,7 +73,7 @@ class NoiseModel(metaclass=value.ABCMetaImplementAnyOneOf):
|
|
|
73
73
|
|
|
74
74
|
raise TypeError(
|
|
75
75
|
'Expected a NOISE_MODEL_LIKE (None, a cirq.NoiseModel, '
|
|
76
|
-
'or a single qubit gate). Got {!r}'
|
|
76
|
+
f'or a single qubit gate). Got {noise!r}'
|
|
77
77
|
)
|
|
78
78
|
|
|
79
79
|
def is_virtual_moment(self, moment: 'cirq.Moment') -> bool:
|
|
@@ -125,6 +125,7 @@ class NoiseModel(metaclass=value.ABCMetaImplementAnyOneOf):
|
|
|
125
125
|
A sequence of OP_TREEs, with the k'th tree corresponding to the
|
|
126
126
|
noisy operations for the k'th moment.
|
|
127
127
|
"""
|
|
128
|
+
raise NotImplementedError
|
|
128
129
|
|
|
129
130
|
def _noisy_moment_impl_moments(
|
|
130
131
|
self, moment: 'cirq.Moment', system_qubits: Sequence['cirq.Qid']
|
|
@@ -150,6 +151,7 @@ class NoiseModel(metaclass=value.ABCMetaImplementAnyOneOf):
|
|
|
150
151
|
Returns:
|
|
151
152
|
An OP_TREE corresponding to the noisy operations for the moment.
|
|
152
153
|
"""
|
|
154
|
+
raise NotImplementedError
|
|
153
155
|
|
|
154
156
|
def _noisy_operation_impl_moments(self, operation: 'cirq.Operation') -> 'cirq.OP_TREE':
|
|
155
157
|
return self.noisy_moments([moment_module.Moment([operation])], operation.qubits)
|
|
@@ -169,6 +171,7 @@ class NoiseModel(metaclass=value.ABCMetaImplementAnyOneOf):
|
|
|
169
171
|
An OP_TREE corresponding to the noisy operations implementing the
|
|
170
172
|
noisy version of the given operation.
|
|
171
173
|
"""
|
|
174
|
+
raise NotImplementedError
|
|
172
175
|
|
|
173
176
|
|
|
174
177
|
@value.value_equality
|
|
@@ -27,9 +27,7 @@ if TYPE_CHECKING:
|
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
# TODO: missing per-device defaults
|
|
30
|
-
|
|
31
|
-
# https://github.com/python/mypy/issues/5374
|
|
32
|
-
@dataclass # type: ignore
|
|
30
|
+
@dataclass
|
|
33
31
|
class SuperconductingQubitsNoiseProperties(devices.NoiseProperties, abc.ABC):
|
|
34
32
|
"""Noise-defining properties for a superconducting-qubit-based device.
|
|
35
33
|
|
|
@@ -134,7 +134,7 @@ def state_tomography(
|
|
|
134
134
|
qubits: Sequence['cirq.Qid'],
|
|
135
135
|
circuit: 'cirq.Circuit',
|
|
136
136
|
repetitions: int = 1000,
|
|
137
|
-
prerotations: Sequence[Tuple[float, float]] = None,
|
|
137
|
+
prerotations: Optional[Sequence[Tuple[float, float]]] = None,
|
|
138
138
|
) -> TomographyResult:
|
|
139
139
|
"""This performs n qubit tomography on a cirq circuit
|
|
140
140
|
|
|
@@ -542,8 +542,8 @@ def _matrix_bar_plot(
|
|
|
542
542
|
mat: np.ndarray,
|
|
543
543
|
z_label: str,
|
|
544
544
|
ax: plt.Axes,
|
|
545
|
-
kets: Sequence[str] = None,
|
|
546
|
-
title: str = None,
|
|
545
|
+
kets: Optional[Sequence[str]] = None,
|
|
546
|
+
title: Optional[str] = None,
|
|
547
547
|
ylim: Tuple[int, int] = (-1, 1),
|
|
548
548
|
**bar3d_kwargs: Any,
|
|
549
549
|
) -> None:
|
|
@@ -111,7 +111,7 @@ def estimate_parallel_single_qubit_readout_errors(
|
|
|
111
111
|
trials: int = 20,
|
|
112
112
|
repetitions: int = 1000,
|
|
113
113
|
trials_per_batch: Optional[int] = None,
|
|
114
|
-
bit_strings: np.ndarray = None,
|
|
114
|
+
bit_strings: Optional[np.ndarray] = None,
|
|
115
115
|
) -> SingleQubitReadoutCalibrationResult:
|
|
116
116
|
"""Estimate single qubit readout error using parallel operations.
|
|
117
117
|
|
|
@@ -45,7 +45,7 @@ def t2_decay(
|
|
|
45
45
|
min_delay: 'cirq.DURATION_LIKE' = None,
|
|
46
46
|
repetitions: int = 1000,
|
|
47
47
|
delay_sweep: Optional[study.Sweep] = None,
|
|
48
|
-
num_pulses: List[int] = None,
|
|
48
|
+
num_pulses: Optional[List[int]] = None,
|
|
49
49
|
) -> Union['cirq.experiments.T2DecayResult', List['cirq.experiments.T2DecayResult']]:
|
|
50
50
|
"""Runs a t2 transverse relaxation experiment.
|
|
51
51
|
|
|
@@ -59,7 +59,7 @@ def test_simulate_circuit_length_validation():
|
|
|
59
59
|
)
|
|
60
60
|
for _ in range(2)
|
|
61
61
|
]
|
|
62
|
-
cycle_depths = np.arange(3, 50, 9)
|
|
62
|
+
cycle_depths = np.arange(3, 50, 9, dtype=np.int64)
|
|
63
63
|
with pytest.raises(ValueError, match='.*not long enough.*'):
|
|
64
64
|
_ = simulate_2q_xeb_circuits(circuits=circuits, cycle_depths=cycle_depths)
|
|
65
65
|
|
|
@@ -127,7 +127,7 @@ def test_incremental_simulate(multiprocess):
|
|
|
127
127
|
)
|
|
128
128
|
for _ in range(20)
|
|
129
129
|
]
|
|
130
|
-
cycle_depths = np.arange(3, 100, 9)
|
|
130
|
+
cycle_depths = np.arange(3, 100, 9, dtype=np.int64)
|
|
131
131
|
|
|
132
132
|
if multiprocess:
|
|
133
133
|
pool = multiprocessing.Pool()
|
cirq/json_resolver_cache.py
CHANGED
|
@@ -241,6 +241,7 @@ def _class_resolver_dictionary() -> Dict[str, ObjectFactory]:
|
|
|
241
241
|
'YYPowGate': cirq.YYPowGate,
|
|
242
242
|
'_ZEigenState': cirq.value.product_state._ZEigenState,
|
|
243
243
|
'Zip': cirq.Zip,
|
|
244
|
+
'ZipLongest': cirq.ZipLongest,
|
|
244
245
|
'ZPowGate': cirq.ZPowGate,
|
|
245
246
|
'ZZPowGate': cirq.ZZPowGate,
|
|
246
247
|
# Old types, only supported for backwards-compatibility
|
cirq/linalg/__init__.py
CHANGED
|
@@ -367,12 +367,12 @@ def test_kak_repr():
|
|
|
367
367
|
cirq.KakDecomposition(
|
|
368
368
|
interaction_coefficients=(0.5, 0.25, 0),
|
|
369
369
|
single_qubit_operations_before=(
|
|
370
|
-
np.array([[0j, (1+0j)], [(1+0j), 0j]], dtype=np.complex128),
|
|
371
|
-
np.array([[0j, -1j], [1j, 0j]], dtype=np.complex128),
|
|
370
|
+
np.array([[0j, (1+0j)], [(1+0j), 0j]], dtype=np.dtype('complex128')),
|
|
371
|
+
np.array([[0j, -1j], [1j, 0j]], dtype=np.dtype('complex128')),
|
|
372
372
|
),
|
|
373
373
|
single_qubit_operations_after=(
|
|
374
|
-
np.array([[1.0, 0.0], [0.0, 1.0]], dtype=np.float64),
|
|
375
|
-
np.array([[(1+0j), 0j], [0j, (-1+0j)]], dtype=np.complex128),
|
|
374
|
+
np.array([[1.0, 0.0], [0.0, 1.0]], dtype=np.dtype('float64')),
|
|
375
|
+
np.array([[(1+0j), 0j], [0j, (-1+0j)]], dtype=np.dtype('complex128')),
|
|
376
376
|
),
|
|
377
377
|
global_phase=1)
|
|
378
378
|
""".strip()
|
cirq/linalg/diagonalize_test.py
CHANGED
|
@@ -60,8 +60,9 @@ def random_bi_diagonalizable_pair(
|
|
|
60
60
|
|
|
61
61
|
|
|
62
62
|
def _get_assert_diagonalized_by_str(m, p, d):
|
|
63
|
-
return
|
|
64
|
-
|
|
63
|
+
return (
|
|
64
|
+
f'm.round(3) : {np.round(m, 3)}, p.round(3) : {np.round(p, 3)}, '
|
|
65
|
+
f'np.abs(p.T @ m @ p).round(2): {np.abs(d).round(2)}'
|
|
65
66
|
)
|
|
66
67
|
|
|
67
68
|
|
|
@@ -75,10 +76,8 @@ def assert_diagonalized_by(m, p, atol: float = 1e-8):
|
|
|
75
76
|
|
|
76
77
|
def _get_assert_bidiagonalized_by_str(m, p, q, d):
|
|
77
78
|
return (
|
|
78
|
-
'm.round(3) : {}, p.round(3) : {
|
|
79
|
-
'np.abs(p.T @ m @ p).round(2): {}'
|
|
80
|
-
np.round(m, 3), np.round(p, 3), np.round(q, 3), np.abs(d).round(2)
|
|
81
|
-
)
|
|
79
|
+
f'm.round(3) : {np.round(m, 3)}, p.round(3) : {np.round(p, 3)}, '
|
|
80
|
+
f'q.round(3): {np.round(q, 3)}, np.abs(p.T @ m @ p).round(2): {np.abs(d).round(2)}'
|
|
82
81
|
)
|
|
83
82
|
|
|
84
83
|
|