Ansatz generation (qiskit_addon_aqc_tensor.ansatz_generation
)¶
Tools for generating ansatz circuits.
Ansatz block. |
|
One-qubit ansatz block. |
|
Two-qubit ansatz block. |
|
One-qubit ansatz block based on the ZXZ decomposition. |
|
Two-qubit ansatz block based on the KAK decomposition. |
- generate_ansatz_from_circuit(qc, /, *, qubits_initially_zero=False, parameter_name='theta')[source][source]¶
Generate an ansatz from the two-qubit connectivity structure of a circuit.
See the explanatatory material for motivation.
- Parameters:
qc (
QuantumCircuit
) – A circuit, which is assumed to be unitary. Barriers are ignored.qubits_initially_zero (
bool
) – IfTrue
, the first Z rotation on each qubit is fixed to zero because such a rotation has no effect on the state \(|0\rangle\).parameter_name (
str
) – Name for theParameterVector
representing the free parameters in the returned ansatz circuit.
- Return type:
- Returns:
(ansatz, parameter_values)
such thatansatz.assign_parameters(parameter_values)
is equivalent toqc
up to a global phase.
Example:¶
Consider the following circuit as an example:
from qiskit import QuantumCircuit qc = QuantumCircuit(6) qc.rx(0.4, 0) qc.ryy(0.2, 2, 3) qc.h(2) qc.rz(0.1, 2) qc.rxx(0.3, 0, 1) qc.rzz(0.3, 0, 1) qc.cx(2, 1) qc.s(1) qc.h(4) qc.draw("mpl")
If the above circuit is passed to
generate_ansatz_from_circuit()
, it will return an ansatz with parametrized two-qubit KAK rotations in the same locations as the input:from qiskit_addon_aqc_tensor import generate_ansatz_from_circuit ansatz, initial_params = generate_ansatz_from_circuit( qc, qubits_initially_zero=True, parameter_name="x" ) ansatz.draw("mpl")
Note that in the generated ansatz, all consecutive single-qubit gates are collapsed into the same ZXZ block, and all consecutive two-qubit gates are collapsed into a single KAK block, up to single-qubit rotations.
Further, the
generate_ansatz_from_circuit()
function provides parameters which, when bound to the ansatz, will result in a circuit equivalent to the original one, up to a global phase:ansatz.assign_parameters(initial_params).draw("mpl")
A 1D Trotter circuit leads to a similar result, with its characteristic brickwork structure:
from rustworkx.generators import path_graph from qiskit.synthesis import SuzukiTrotter from qiskit_addon_utils.problem_generators import generate_time_evolution_circuit, generate_xyz_hamiltonian hamiltonian = generate_xyz_hamiltonian( path_graph(6), coupling_constants=(0.0, 0.0, 1.0), ext_magnetic_field=(0.4, 0.0, 0.0), ) good_circuit = generate_time_evolution_circuit( hamiltonian, synthesis=SuzukiTrotter(reps=2), time=1.0, ) good_circuit.draw("mpl", initial_state=True)
from qiskit_addon_aqc_tensor import generate_ansatz_from_circuit ansatz, initial_params = generate_ansatz_from_circuit( good_circuit, qubits_initially_zero=True, parameter_name="x" ) ansatz.assign_parameters(initial_params).draw("mpl", initial_state=True)
- parametrize_circuit(qc, /, *, parameter_name='theta')[source][source]¶
Create a parametrized version of a circuit.
Given a quantum circuit, constructs another quantum circuit which is identical except that any gates with numerical parameters are replaced by gates (of the same type) with free parameters. The new circuit is returned along with a list containing the original values of the parameters.
- Parameters:
qc (QuantumCircuit) – The quantum circuit to parametrize.
parameter_name (str) – Name for the
ParameterVector
representing the free parameters in the returned ansatz circuit.
- Return type:
tuple[QuantumCircuit, list[float | None]]
- Returns:
(ansatz, parameter_values)
such thatansatz.assign_parameters(parameter_values)
is identical toqc
as long asqc
did not already contain parameters. Ifqc
already had parameters, thenparameter_values
will containNone
at the entries corresponding to those parameters.
Example:¶
Consider the following circuit as an example:
from qiskit import QuantumCircuit qc = QuantumCircuit(6) qc.rx(0.4, 0) qc.ryy(0.2, 2, 3) qc.h(2) qc.rz(0.1, 2) qc.rxx(0.3, 0, 1) qc.rzz(0.3, 0, 1) qc.cx(2, 1) qc.s(1) qc.h(4) qc.draw("mpl")
If the above circuit is passed to
parametrize_circuit()
, it will return an ansatz obtained from this circuit by replacing numerical parameters with free parameters:from qiskit_addon_aqc_tensor import parametrize_circuit ansatz, initial_params = parametrize_circuit(qc) ansatz.draw("mpl")
Further, the
parametrize_circuit()
function provides parameters which, when bound to the ansatz, will result in a circuit identical to the original one:ansatz.assign_parameters(initial_params).draw("mpl")
If the original circuit already contained parameters, then the returned parameter values will contain
None
at the entries corresponding to those parameters, and the preceding code will not work. The following example shows how to recover the original circuit in this case.from qiskit.circuit import Parameter qc = QuantumCircuit(3) alpha1 = Parameter("alpha1") alpha2 = Parameter("alpha2") qc.ry(alpha1, [0]) qc.rz(0.1, [0]) qc.ry(alpha2, [1]) qc.rz(alpha1, [1]) qc.ry(0.2, [2]) qc.rz(0.3, [2]) ansatz, initial_params = parametrize_circuit(qc) ansatz.assign_parameters( { param: val for param, val in zip(ansatz.parameters, initial_params) if val is not None }, inplace=True, ) ansatz.draw("mpl")