qiskit 2.0.2__cp39-abi3-macosx_11_0_arm64.whl → 2.1.0rc1__cp39-abi3-macosx_11_0_arm64.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.
- qiskit/VERSION.txt +1 -1
- qiskit/__init__.py +19 -1
- qiskit/_accelerate.abi3.so +0 -0
- qiskit/circuit/__init__.py +13 -21
- qiskit/circuit/_add_control.py +57 -31
- qiskit/circuit/_classical_resource_map.py +4 -0
- qiskit/circuit/annotation.py +404 -0
- qiskit/circuit/classical/expr/__init__.py +1 -1
- qiskit/circuit/classical/expr/expr.py +104 -446
- qiskit/circuit/classical/expr/visitors.py +6 -0
- qiskit/circuit/classical/types/types.py +7 -130
- qiskit/circuit/controlflow/box.py +32 -7
- qiskit/circuit/delay.py +11 -9
- qiskit/circuit/library/arithmetic/adders/adder.py +5 -5
- qiskit/circuit/library/arithmetic/multipliers/multiplier.py +3 -3
- qiskit/circuit/library/arithmetic/piecewise_chebyshev.py +7 -3
- qiskit/circuit/library/arithmetic/piecewise_linear_pauli_rotations.py +23 -15
- qiskit/circuit/library/arithmetic/piecewise_polynomial_pauli_rotations.py +22 -14
- qiskit/circuit/library/arithmetic/quadratic_form.py +6 -0
- qiskit/circuit/library/arithmetic/weighted_adder.py +43 -24
- qiskit/circuit/library/basis_change/qft.py +2 -2
- qiskit/circuit/library/blueprintcircuit.py +6 -0
- qiskit/circuit/library/boolean_logic/inner_product.py +2 -2
- qiskit/circuit/library/boolean_logic/quantum_and.py +2 -2
- qiskit/circuit/library/boolean_logic/quantum_or.py +3 -3
- qiskit/circuit/library/boolean_logic/quantum_xor.py +2 -2
- qiskit/circuit/library/data_preparation/_z_feature_map.py +2 -2
- qiskit/circuit/library/data_preparation/_zz_feature_map.py +2 -2
- qiskit/circuit/library/data_preparation/pauli_feature_map.py +2 -2
- qiskit/circuit/library/fourier_checking.py +2 -2
- qiskit/circuit/library/generalized_gates/diagonal.py +5 -1
- qiskit/circuit/library/generalized_gates/gms.py +5 -1
- qiskit/circuit/library/generalized_gates/linear_function.py +2 -2
- qiskit/circuit/library/generalized_gates/permutation.py +5 -1
- qiskit/circuit/library/generalized_gates/uc.py +1 -1
- qiskit/circuit/library/generalized_gates/unitary.py +21 -2
- qiskit/circuit/library/graph_state.py +2 -2
- qiskit/circuit/library/grover_operator.py +2 -2
- qiskit/circuit/library/hidden_linear_function.py +2 -2
- qiskit/circuit/library/iqp.py +2 -2
- qiskit/circuit/library/n_local/efficient_su2.py +2 -2
- qiskit/circuit/library/n_local/evolved_operator_ansatz.py +1 -1
- qiskit/circuit/library/n_local/excitation_preserving.py +7 -9
- qiskit/circuit/library/n_local/n_local.py +4 -3
- qiskit/circuit/library/n_local/pauli_two_design.py +2 -2
- qiskit/circuit/library/n_local/real_amplitudes.py +2 -2
- qiskit/circuit/library/n_local/two_local.py +2 -2
- qiskit/circuit/library/overlap.py +2 -2
- qiskit/circuit/library/pauli_evolution.py +3 -2
- qiskit/circuit/library/phase_estimation.py +2 -2
- qiskit/circuit/library/standard_gates/dcx.py +11 -12
- qiskit/circuit/library/standard_gates/ecr.py +21 -24
- qiskit/circuit/library/standard_gates/equivalence_library.py +232 -96
- qiskit/circuit/library/standard_gates/global_phase.py +5 -6
- qiskit/circuit/library/standard_gates/h.py +22 -45
- qiskit/circuit/library/standard_gates/i.py +1 -1
- qiskit/circuit/library/standard_gates/iswap.py +13 -31
- qiskit/circuit/library/standard_gates/p.py +19 -26
- qiskit/circuit/library/standard_gates/r.py +11 -17
- qiskit/circuit/library/standard_gates/rx.py +21 -45
- qiskit/circuit/library/standard_gates/rxx.py +7 -22
- qiskit/circuit/library/standard_gates/ry.py +21 -39
- qiskit/circuit/library/standard_gates/ryy.py +13 -28
- qiskit/circuit/library/standard_gates/rz.py +18 -35
- qiskit/circuit/library/standard_gates/rzx.py +7 -22
- qiskit/circuit/library/standard_gates/rzz.py +7 -19
- qiskit/circuit/library/standard_gates/s.py +44 -39
- qiskit/circuit/library/standard_gates/swap.py +25 -38
- qiskit/circuit/library/standard_gates/sx.py +34 -41
- qiskit/circuit/library/standard_gates/t.py +18 -27
- qiskit/circuit/library/standard_gates/u.py +8 -24
- qiskit/circuit/library/standard_gates/u1.py +28 -52
- qiskit/circuit/library/standard_gates/u2.py +9 -9
- qiskit/circuit/library/standard_gates/u3.py +24 -40
- qiskit/circuit/library/standard_gates/x.py +190 -336
- qiskit/circuit/library/standard_gates/xx_minus_yy.py +12 -50
- qiskit/circuit/library/standard_gates/xx_plus_yy.py +13 -52
- qiskit/circuit/library/standard_gates/y.py +19 -23
- qiskit/circuit/library/standard_gates/z.py +31 -38
- qiskit/circuit/parameter.py +14 -5
- qiskit/circuit/parameterexpression.py +109 -75
- qiskit/circuit/quantumcircuit.py +168 -98
- qiskit/circuit/quantumcircuitdata.py +1 -0
- qiskit/circuit/random/__init__.py +37 -2
- qiskit/circuit/random/utils.py +445 -56
- qiskit/circuit/tools/pi_check.py +5 -13
- qiskit/compiler/transpiler.py +1 -1
- qiskit/converters/circuit_to_instruction.py +2 -2
- qiskit/dagcircuit/dagnode.py +8 -3
- qiskit/primitives/__init__.py +2 -2
- qiskit/primitives/base/base_estimator.py +2 -2
- qiskit/primitives/containers/data_bin.py +0 -3
- qiskit/primitives/containers/observables_array.py +192 -108
- qiskit/primitives/primitive_job.py +29 -10
- qiskit/providers/fake_provider/generic_backend_v2.py +2 -0
- qiskit/qasm3/__init__.py +106 -12
- qiskit/qasm3/ast.py +15 -1
- qiskit/qasm3/exporter.py +59 -36
- qiskit/qasm3/printer.py +12 -0
- qiskit/qpy/__init__.py +183 -7
- qiskit/qpy/binary_io/circuits.py +256 -24
- qiskit/qpy/binary_io/parse_sympy_repr.py +5 -0
- qiskit/qpy/binary_io/schedules.py +12 -32
- qiskit/qpy/binary_io/value.py +36 -18
- qiskit/qpy/common.py +11 -3
- qiskit/qpy/formats.py +17 -1
- qiskit/qpy/interface.py +52 -12
- qiskit/qpy/type_keys.py +7 -1
- qiskit/quantum_info/__init__.py +10 -0
- qiskit/quantum_info/operators/__init__.py +1 -0
- qiskit/quantum_info/operators/symplectic/__init__.py +1 -0
- qiskit/quantum_info/operators/symplectic/clifford_circuits.py +26 -0
- qiskit/quantum_info/operators/symplectic/pauli.py +2 -2
- qiskit/quantum_info/operators/symplectic/sparse_pauli_op.py +1 -1
- qiskit/result/sampled_expval.py +3 -1
- qiskit/synthesis/__init__.py +10 -0
- qiskit/synthesis/arithmetic/__init__.py +1 -1
- qiskit/synthesis/arithmetic/adders/__init__.py +1 -0
- qiskit/synthesis/arithmetic/adders/draper_qft_adder.py +6 -2
- qiskit/synthesis/arithmetic/adders/rv_ripple_carry_adder.py +156 -0
- qiskit/synthesis/discrete_basis/generate_basis_approximations.py +14 -126
- qiskit/synthesis/discrete_basis/solovay_kitaev.py +161 -121
- qiskit/synthesis/evolution/lie_trotter.py +10 -7
- qiskit/synthesis/evolution/product_formula.py +10 -7
- qiskit/synthesis/evolution/qdrift.py +10 -7
- qiskit/synthesis/evolution/suzuki_trotter.py +10 -7
- qiskit/synthesis/multi_controlled/__init__.py +4 -0
- qiskit/synthesis/multi_controlled/mcx_synthesis.py +402 -178
- qiskit/synthesis/multi_controlled/multi_control_rotation_gates.py +14 -15
- qiskit/synthesis/qft/qft_decompose_lnn.py +7 -25
- qiskit/synthesis/unitary/qsd.py +80 -9
- qiskit/transpiler/__init__.py +19 -8
- qiskit/transpiler/instruction_durations.py +2 -20
- qiskit/transpiler/passes/__init__.py +4 -2
- qiskit/transpiler/passes/layout/dense_layout.py +26 -6
- qiskit/transpiler/passes/layout/disjoint_utils.py +1 -166
- qiskit/transpiler/passes/layout/sabre_layout.py +22 -3
- qiskit/transpiler/passes/layout/sabre_pre_layout.py +1 -1
- qiskit/transpiler/passes/layout/vf2_layout.py +49 -13
- qiskit/transpiler/passes/layout/vf2_utils.py +13 -1
- qiskit/transpiler/passes/optimization/__init__.py +1 -1
- qiskit/transpiler/passes/optimization/optimize_1q_decomposition.py +2 -1
- qiskit/transpiler/passes/optimization/optimize_clifford_t.py +68 -0
- qiskit/transpiler/passes/optimization/template_matching/template_substitution.py +3 -9
- qiskit/transpiler/passes/routing/sabre_swap.py +12 -2
- qiskit/transpiler/passes/routing/star_prerouting.py +106 -81
- qiskit/transpiler/passes/scheduling/__init__.py +1 -1
- qiskit/transpiler/passes/scheduling/alignments/check_durations.py +1 -1
- qiskit/transpiler/passes/scheduling/padding/__init__.py +1 -0
- qiskit/transpiler/passes/scheduling/padding/context_aware_dynamical_decoupling.py +876 -0
- qiskit/transpiler/passes/synthesis/__init__.py +1 -0
- qiskit/transpiler/passes/synthesis/clifford_unitary_synth_plugin.py +123 -0
- qiskit/transpiler/passes/synthesis/hls_plugins.py +472 -92
- qiskit/transpiler/passes/synthesis/solovay_kitaev_synthesis.py +27 -22
- qiskit/transpiler/passmanager_config.py +3 -0
- qiskit/transpiler/preset_passmanagers/builtin_plugins.py +149 -28
- qiskit/transpiler/preset_passmanagers/common.py +101 -0
- qiskit/transpiler/preset_passmanagers/generate_preset_pass_manager.py +6 -0
- qiskit/transpiler/preset_passmanagers/level3.py +2 -2
- qiskit/utils/optionals.py +6 -5
- qiskit/visualization/circuit/_utils.py +5 -3
- qiskit/visualization/circuit/latex.py +9 -2
- qiskit/visualization/circuit/matplotlib.py +26 -4
- qiskit/visualization/circuit/qcstyle.py +9 -157
- qiskit/visualization/dag/__init__.py +13 -0
- qiskit/visualization/dag/dagstyle.py +103 -0
- qiskit/visualization/dag/styles/__init__.py +13 -0
- qiskit/visualization/dag/styles/color.json +10 -0
- qiskit/visualization/dag/styles/plain.json +5 -0
- qiskit/visualization/dag_visualization.py +169 -98
- qiskit/visualization/style.py +223 -0
- {qiskit-2.0.2.dist-info → qiskit-2.1.0rc1.dist-info}/METADATA +14 -13
- {qiskit-2.0.2.dist-info → qiskit-2.1.0rc1.dist-info}/RECORD +177 -168
- {qiskit-2.0.2.dist-info → qiskit-2.1.0rc1.dist-info}/entry_points.txt +6 -0
- qiskit/synthesis/discrete_basis/commutator_decompose.py +0 -265
- qiskit/synthesis/discrete_basis/gate_sequence.py +0 -421
- {qiskit-2.0.2.dist-info → qiskit-2.1.0rc1.dist-info}/WHEEL +0 -0
- {qiskit-2.0.2.dist-info → qiskit-2.1.0rc1.dist-info}/licenses/LICENSE.txt +0 -0
- {qiskit-2.0.2.dist-info → qiskit-2.1.0rc1.dist-info}/top_level.txt +0 -0
@@ -5,6 +5,7 @@ FullAdder.ripple_v95 = qiskit.transpiler.passes.synthesis.hls_plugins:FullAdderS
|
|
5
5
|
HalfAdder.default = qiskit.transpiler.passes.synthesis.hls_plugins:HalfAdderSynthesisDefault
|
6
6
|
HalfAdder.qft_d00 = qiskit.transpiler.passes.synthesis.hls_plugins:HalfAdderSynthesisD00
|
7
7
|
HalfAdder.ripple_c04 = qiskit.transpiler.passes.synthesis.hls_plugins:HalfAdderSynthesisC04
|
8
|
+
HalfAdder.ripple_r25 = qiskit.transpiler.passes.synthesis.hls_plugins:HalfAdderSynthesisR25
|
8
9
|
HalfAdder.ripple_v95 = qiskit.transpiler.passes.synthesis.hls_plugins:HalfAdderSynthesisV95
|
9
10
|
IntComp.default = qiskit.transpiler.passes.synthesis.hls_plugins:IntComparatorSynthesisDefault
|
10
11
|
IntComp.noaux = qiskit.transpiler.passes.synthesis.hls_plugins:IntComparatorSynthesisNoAux
|
@@ -33,6 +34,10 @@ mcmt.default = qiskit.transpiler.passes.synthesis.hls_plugins:MCMTSynthesisDefau
|
|
33
34
|
mcmt.noaux = qiskit.transpiler.passes.synthesis.hls_plugins:MCMTSynthesisNoAux
|
34
35
|
mcmt.vchain = qiskit.transpiler.passes.synthesis.hls_plugins:MCMTSynthesisVChain
|
35
36
|
mcx.1_clean_b95 = qiskit.transpiler.passes.synthesis.hls_plugins:MCXSynthesis1CleanB95
|
37
|
+
mcx.1_clean_kg24 = qiskit.transpiler.passes.synthesis.hls_plugins:MCXSynthesis1CleanKG24
|
38
|
+
mcx.1_dirty_kg24 = qiskit.transpiler.passes.synthesis.hls_plugins:MCXSynthesis1DirtyKG24
|
39
|
+
mcx.2_clean_kg24 = qiskit.transpiler.passes.synthesis.hls_plugins:MCXSynthesis2CleanKG24
|
40
|
+
mcx.2_dirty_kg24 = qiskit.transpiler.passes.synthesis.hls_plugins:MCXSynthesis2DirtyKG24
|
36
41
|
mcx.default = qiskit.transpiler.passes.synthesis.hls_plugins:MCXSynthesisDefault
|
37
42
|
mcx.gray_code = qiskit.transpiler.passes.synthesis.hls_plugins:MCXSynthesisGrayCode
|
38
43
|
mcx.n_clean_m15 = qiskit.transpiler.passes.synthesis.hls_plugins:MCXSynthesisNCleanM15
|
@@ -78,5 +83,6 @@ translator = qiskit.transpiler.preset_passmanagers.builtin_plugins:BasisTranslat
|
|
78
83
|
|
79
84
|
[qiskit.unitary_synthesis]
|
80
85
|
aqc = qiskit.transpiler.passes.synthesis.aqc_plugin:AQCSynthesisPlugin
|
86
|
+
clifford = qiskit.transpiler.passes.synthesis.clifford_unitary_synth_plugin:CliffordUnitarySynthesis
|
81
87
|
default = qiskit.transpiler.passes.synthesis.default_unitary_synth_plugin:DefaultUnitarySynthesis
|
82
88
|
sk = qiskit.transpiler.passes.synthesis.solovay_kitaev_synthesis:SolovayKitaevSynthesis
|
@@ -1,265 +0,0 @@
|
|
1
|
-
# This code is part of Qiskit.
|
2
|
-
#
|
3
|
-
# (C) Copyright IBM 2017, 2022.
|
4
|
-
#
|
5
|
-
# This code is licensed under the Apache License, Version 2.0. You may
|
6
|
-
# obtain a copy of this license in the LICENSE.txt file in the root directory
|
7
|
-
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
|
8
|
-
#
|
9
|
-
# Any modifications or derivative works of this code must retain this
|
10
|
-
# copyright notice, and modified files need to carry a notice indicating
|
11
|
-
# that they have been altered from the originals.
|
12
|
-
|
13
|
-
"""Functions to compute the decomposition of an SO(3) matrix as balanced commutator."""
|
14
|
-
|
15
|
-
from __future__ import annotations
|
16
|
-
|
17
|
-
import math
|
18
|
-
import numpy as np
|
19
|
-
from qiskit.quantum_info.operators.predicates import is_identity_matrix
|
20
|
-
from .gate_sequence import _check_is_so3, GateSequence
|
21
|
-
|
22
|
-
|
23
|
-
def _compute_trace_so3(matrix: np.ndarray) -> float:
|
24
|
-
"""Computes trace of an SO(3)-matrix.
|
25
|
-
|
26
|
-
Args:
|
27
|
-
matrix: an SO(3)-matrix
|
28
|
-
|
29
|
-
Returns:
|
30
|
-
Trace of ``matrix``.
|
31
|
-
|
32
|
-
Raises:
|
33
|
-
ValueError: if ``matrix`` is not an SO(3)-matrix.
|
34
|
-
"""
|
35
|
-
_check_is_so3(matrix)
|
36
|
-
|
37
|
-
trace = np.matrix.trace(matrix)
|
38
|
-
trace_rounded = min(trace, 3)
|
39
|
-
return trace_rounded
|
40
|
-
|
41
|
-
|
42
|
-
def _compute_rotation_axis(matrix: np.ndarray) -> np.ndarray:
|
43
|
-
"""Computes rotation axis of SO(3)-matrix.
|
44
|
-
|
45
|
-
Args:
|
46
|
-
matrix: The SO(3)-matrix for which rotation angle needs to be computed.
|
47
|
-
|
48
|
-
Returns:
|
49
|
-
The rotation axis of the SO(3)-matrix ``matrix``.
|
50
|
-
|
51
|
-
Raises:
|
52
|
-
ValueError: if ``matrix`` is not an SO(3)-matrix.
|
53
|
-
"""
|
54
|
-
_check_is_so3(matrix)
|
55
|
-
|
56
|
-
# If theta represents the rotation angle, then trace = 1 + 2cos(theta).
|
57
|
-
trace = _compute_trace_so3(matrix)
|
58
|
-
|
59
|
-
if trace >= 3 - 1e-10:
|
60
|
-
# The matrix is the identity (rotation by 0)
|
61
|
-
x = 1.0
|
62
|
-
y = 0.0
|
63
|
-
z = 0.0
|
64
|
-
|
65
|
-
elif trace <= -1 + 1e-10:
|
66
|
-
# The matrix is the 180-degree rotation
|
67
|
-
squares = (1 + np.diagonal(matrix)) / 2
|
68
|
-
index_of_max = np.argmax(squares)
|
69
|
-
|
70
|
-
if index_of_max == 0:
|
71
|
-
x = math.sqrt(squares[0])
|
72
|
-
y = matrix[0][1] / (2 * x)
|
73
|
-
z = matrix[0][2] / (2 * x)
|
74
|
-
elif index_of_max == 1:
|
75
|
-
y = math.sqrt(squares[1])
|
76
|
-
x = matrix[0][1] / (2 * y)
|
77
|
-
z = matrix[1][2] / (2 * y)
|
78
|
-
else:
|
79
|
-
z = math.sqrt(squares[2])
|
80
|
-
x = matrix[0][2] / (2 * z)
|
81
|
-
y = matrix[1][2] / (2 * z)
|
82
|
-
|
83
|
-
else:
|
84
|
-
# The matrix is the rotation by theta with sin(theta)!=0
|
85
|
-
theta = math.acos(0.5 * (trace - 1))
|
86
|
-
x = 1 / (2 * math.sin(theta)) * (matrix[2][1] - matrix[1][2])
|
87
|
-
y = 1 / (2 * math.sin(theta)) * (matrix[0][2] - matrix[2][0])
|
88
|
-
z = 1 / (2 * math.sin(theta)) * (matrix[1][0] - matrix[0][1])
|
89
|
-
|
90
|
-
return np.array([x, y, z])
|
91
|
-
|
92
|
-
|
93
|
-
def _solve_decomposition_angle(matrix: np.ndarray) -> float:
|
94
|
-
"""Computes angle for balanced commutator of SO(3)-matrix ``matrix``.
|
95
|
-
|
96
|
-
Computes angle a so that the SO(3)-matrix ``matrix`` can be decomposed
|
97
|
-
as commutator [v,w] where v and w are both rotations of a about some axis.
|
98
|
-
The computation is done by solving a trigonometric equation using scipy.optimize.fsolve.
|
99
|
-
|
100
|
-
Args:
|
101
|
-
matrix: The SO(3)-matrix for which the decomposition angle needs to be computed.
|
102
|
-
|
103
|
-
Returns:
|
104
|
-
Angle a so that matrix = [v,w] with v and w rotations of a about some axis.
|
105
|
-
|
106
|
-
Raises:
|
107
|
-
ValueError: if ``matrix`` is not an SO(3)-matrix.
|
108
|
-
"""
|
109
|
-
from scipy.optimize import fsolve
|
110
|
-
|
111
|
-
_check_is_so3(matrix)
|
112
|
-
|
113
|
-
trace = _compute_trace_so3(matrix)
|
114
|
-
angle = math.acos((1 / 2) * (trace - 1))
|
115
|
-
|
116
|
-
lhs = math.sin(angle / 2)
|
117
|
-
|
118
|
-
def objective(phi):
|
119
|
-
sin_sq = math.sin(phi.item() / 2) ** 2
|
120
|
-
return 2 * sin_sq * math.sqrt(1 - sin_sq**2) - lhs
|
121
|
-
|
122
|
-
decomposition_angle = fsolve(objective, angle)[0]
|
123
|
-
return decomposition_angle
|
124
|
-
|
125
|
-
|
126
|
-
def _compute_rotation_from_angle_and_axis(angle: float, axis: np.ndarray) -> np.ndarray:
|
127
|
-
"""Computes the SO(3)-matrix corresponding to the rotation of ``angle`` about ``axis``.
|
128
|
-
|
129
|
-
Args:
|
130
|
-
angle: The angle of the rotation.
|
131
|
-
axis: The axis of the rotation.
|
132
|
-
|
133
|
-
Returns:
|
134
|
-
SO(3)-matrix that represents a rotation of ``angle`` about ``axis``.
|
135
|
-
|
136
|
-
Raises:
|
137
|
-
ValueError: if ``axis`` is not a 3-dim unit vector.
|
138
|
-
"""
|
139
|
-
if axis.shape != (3,):
|
140
|
-
raise ValueError(f"Axis must be a 1d array of length 3, but has shape {axis.shape}.")
|
141
|
-
|
142
|
-
if abs(np.linalg.norm(axis) - 1.0) > 1e-4:
|
143
|
-
raise ValueError(f"Axis must have a norm of 1, but has {np.linalg.norm(axis)}.")
|
144
|
-
|
145
|
-
res = math.cos(angle) * np.identity(3) + math.sin(angle) * _cross_product_matrix(axis)
|
146
|
-
res += (1 - math.cos(angle)) * np.outer(axis, axis)
|
147
|
-
return res
|
148
|
-
|
149
|
-
|
150
|
-
def _compute_rotation_between(from_vector: np.ndarray, to_vector: np.ndarray) -> np.ndarray:
|
151
|
-
"""Computes the SO(3)-matrix for rotating ``from_vector`` to ``to_vector``.
|
152
|
-
|
153
|
-
Args:
|
154
|
-
from_vector: unit vector of size 3
|
155
|
-
to_vector: unit vector of size 3
|
156
|
-
|
157
|
-
Returns:
|
158
|
-
SO(3)-matrix that brings ``from_vector`` to ``to_vector``.
|
159
|
-
|
160
|
-
Raises:
|
161
|
-
ValueError: if at least one of ``from_vector`` of ``to_vector`` is not a 3-dim unit vector.
|
162
|
-
"""
|
163
|
-
from_vector = from_vector / np.linalg.norm(from_vector)
|
164
|
-
to_vector = to_vector / np.linalg.norm(to_vector)
|
165
|
-
|
166
|
-
dot = np.dot(from_vector, to_vector)
|
167
|
-
cross = _cross_product_matrix(np.cross(from_vector, to_vector))
|
168
|
-
rotation_matrix = np.identity(3) + cross + np.dot(cross, cross) / (1 + dot)
|
169
|
-
return rotation_matrix
|
170
|
-
|
171
|
-
|
172
|
-
def _cross_product_matrix(v: np.ndarray) -> np.ndarray:
|
173
|
-
"""Computes cross product matrix from vector.
|
174
|
-
|
175
|
-
Args:
|
176
|
-
v: Vector for which cross product matrix needs to be computed.
|
177
|
-
|
178
|
-
Returns:
|
179
|
-
The cross product matrix corresponding to vector ``v``.
|
180
|
-
"""
|
181
|
-
return np.array([[0, -v[2], v[1]], [v[2], 0, -v[0]], [-v[1], v[0], 0]])
|
182
|
-
|
183
|
-
|
184
|
-
def _compute_commutator_so3(a: np.ndarray, b: np.ndarray) -> np.ndarray:
|
185
|
-
"""Computes the commutator of the SO(3)-matrices ``a`` and ``b``.
|
186
|
-
|
187
|
-
The computation uses the fact that the inverse of an SO(3)-matrix is equal to its transpose.
|
188
|
-
|
189
|
-
Args:
|
190
|
-
a: SO(3)-matrix
|
191
|
-
b: SO(3)-matrix
|
192
|
-
|
193
|
-
Returns:
|
194
|
-
The commutator [a,b] of ``a`` and ``b`` w
|
195
|
-
|
196
|
-
Raises:
|
197
|
-
ValueError: if at least one of ``a`` or ``b`` is not an SO(3)-matrix.
|
198
|
-
"""
|
199
|
-
_check_is_so3(a)
|
200
|
-
_check_is_so3(b)
|
201
|
-
|
202
|
-
a_dagger = np.conj(a).T
|
203
|
-
b_dagger = np.conj(b).T
|
204
|
-
|
205
|
-
return np.dot(np.dot(np.dot(a, b), a_dagger), b_dagger)
|
206
|
-
|
207
|
-
|
208
|
-
def commutator_decompose(
|
209
|
-
u_so3: np.ndarray, check_input: bool = True
|
210
|
-
) -> tuple[GateSequence, GateSequence]:
|
211
|
-
r"""Decompose an :math:`SO(3)`-matrix, :math:`U` as a balanced commutator.
|
212
|
-
|
213
|
-
This function finds two :math:`SO(3)` matrices :math:`V, W` such that the input matrix
|
214
|
-
equals
|
215
|
-
|
216
|
-
.. math::
|
217
|
-
|
218
|
-
U = V^\dagger W^\dagger V W.
|
219
|
-
|
220
|
-
For this decomposition, the following statement holds
|
221
|
-
|
222
|
-
|
223
|
-
.. math::
|
224
|
-
|
225
|
-
||V - I||_F, ||W - I||_F \leq \frac{\sqrt{||U - I||_F}}{2},
|
226
|
-
|
227
|
-
where :math:`I` is the identity and :math:`||\cdot ||_F` is the Frobenius norm.
|
228
|
-
|
229
|
-
Args:
|
230
|
-
u_so3: SO(3)-matrix that needs to be decomposed as balanced commutator.
|
231
|
-
check_input: If True, checks whether the input matrix is actually SO(3).
|
232
|
-
|
233
|
-
Returns:
|
234
|
-
Tuple of GateSequences from SO(3)-matrices :math:`V, W`.
|
235
|
-
|
236
|
-
Raises:
|
237
|
-
ValueError: if ``u_so3`` is not an SO(3)-matrix.
|
238
|
-
"""
|
239
|
-
if check_input:
|
240
|
-
# assert that the input matrix is really SO(3)
|
241
|
-
_check_is_so3(u_so3)
|
242
|
-
|
243
|
-
if not is_identity_matrix(u_so3.dot(u_so3.T)):
|
244
|
-
raise ValueError("Input matrix is not orthogonal.")
|
245
|
-
|
246
|
-
angle = _solve_decomposition_angle(u_so3)
|
247
|
-
|
248
|
-
# Compute rotation about x-axis with angle 'angle'
|
249
|
-
vx = _compute_rotation_from_angle_and_axis(angle, np.array([1, 0, 0]))
|
250
|
-
|
251
|
-
# Compute rotation about y-axis with angle 'angle'
|
252
|
-
wy = _compute_rotation_from_angle_and_axis(angle, np.array([0, 1, 0]))
|
253
|
-
|
254
|
-
commutator = _compute_commutator_so3(vx, wy)
|
255
|
-
|
256
|
-
u_so3_axis = _compute_rotation_axis(u_so3)
|
257
|
-
commutator_axis = _compute_rotation_axis(commutator)
|
258
|
-
|
259
|
-
sim_matrix = _compute_rotation_between(commutator_axis, u_so3_axis)
|
260
|
-
sim_matrix_dagger = np.conj(sim_matrix).T
|
261
|
-
|
262
|
-
v = np.dot(np.dot(sim_matrix, vx), sim_matrix_dagger)
|
263
|
-
w = np.dot(np.dot(sim_matrix, wy), sim_matrix_dagger)
|
264
|
-
|
265
|
-
return GateSequence.from_matrix(v), GateSequence.from_matrix(w)
|