# qutip_qip.vqa

Variational Quantum Algorithms generation and optimization

Classes

 OptimizationResult(res, final_state) Class for results of VQA optimization loop. Hamiltonian with 0 or more parameterized terms. VQA(num_qubits[, num_layers, cost_method]) Optimizes free parameters to generate QubitCircuit instances based on Variational Quantum Algorithms. VQABlock(operator[, is_unitary, name, ...]) Component of a VQA.
class qutip_qip.vqa.OptimizationResult(res, final_state)[source]

Bases: object

Class for results of VQA optimization loop.

Parameters
res: scipy results instance
final_state:obj:qutip.Qobj

Final state of the circuit after optimization.

get_top_bitstring()[source]

Return the bitstring associated with the highest probability measurement outcome

Returns
bitstring: str

bitstring in the form $$|x_0x_1...x_n>$$ where each $$x_i$$ is 0 or 1 and n is the number of qubits of the system.

plot(S=None, label_sets=False, top_ten=False, display=True)[source]

Plot probability amplitudes of each measurement outcome of a state.

Parameters
S: list of float, optional

Problem instance

min_cost: str, optional

The minimum cost found by optimization

label_sets: bool, optional

Replace bitstring labels with sets referring to the inferred output of the combinatorial optimization problem. For example a bitstring $$|010>$$ would produce a set with the first and last elements of S, and one with the second element of S.

top_ten: bool, optional

Only plot the ten highest-probability states.

display: bool, optional

Display the plot with the pyplot plot.show() method

class qutip_qip.vqa.ParameterizedHamiltonian(parameterized_terms=[], constant_term=None)[source]

Bases: object

Hamiltonian with 0 or more parameterized terms. In general, computes a unitary as $$U = e^{H_0 + p_1 H_1 + P_2 H_2 + \dots}$$

Parameters
parameterized_terms: list ofobj:qutip.Qobj

Hamiltonian terms which each require a unique parameter

constant_term:obj:qutip.Qobj

Hamiltonian term which does not require parameters.

class qutip_qip.vqa.VQA(num_qubits, num_layers=1, cost_method='OBSERVABLE')[source]

Bases: object

Optimizes free parameters to generate QubitCircuit instances based on Variational Quantum Algorithms. Accepts VQABlock elements instead of Gate elements, which allows for easy parameterization of user-defined circuit elements. Includes methods for parameter optimization and generators of QubitCircuit instances.

Parameters
num_qubits: int

number of qubits used by the algorithm

num_layers: int, optional

number of layers used by the algorihtm

cost_method: str

method used to compute the cost of an instance of the circuit constructed by fixing its free parameters. Can be one of OBSERVABLE, BITSTRING or STATE.

1. If OBSERVABLE is set, then the attribute VQA.cost_observable needs to be specified as a Qobj. The cost of the circuit is the expectation value of this observable in the final state.

2. If STATE is set, then VQA.cost_func needs to be specified as a callable that takes in a quantum state, as a Qobj, and returns a float.

3. If BITSTRING is set, then VQA.cost_func needs to be specified as a callable that takes in a bitstring and returns a float.

Append a VQABlock instance to the circuit, and update the user_gates dictionary if necessary.

Parameters
block: VQABlock
compute_jac(angles, indices_to_compute=None)[source]

Compute the jacobian for the circuit’s cost function, assuming the cost function is in observable mode.

Parameters
angles: list of float

Circuit free parameters

indicies_to_compute: list of int, optional

Block indices for which to use in computing the jacobian. By default, this is every index (every block).

Returns
jac: (n,) numpy array of floats
construct_circuit(angles)[source]

Construct a circuit by specifying values for each free parameter.

Parameters
angles: list of float

A list of dimension (n,) for n free parameters in the circuit

Returns
circ:obj:.QubitCircuit
cost_derivative(U, dU)[source]

Returns partial derivative of cost function (in observable mode) with respect to the parameter in the block’s unitary. Assuming a block unitary of the form e^{-iH * theta}, this will return d/(d theta) of the cost function in terms of an observable.

Parameters
U:obj:qutip.Qobj

Block unitary

dU:obj:qutip.Qobj

Partial derivative of U with respect to its parameter

Returns
dCost: float

Partial derivative of cost with respect to block’s parameter

evaluate_parameters(angles)[source]

Evaluate a cost for the circuit, based on the VQA cost method defined.

Parameters
angles: list of float

A list of dimension (n,) for n free parameters in the circuit

Returns
cost: float
export_image(filename='circuit.png')[source]

Export an image of the circuit.

Parameters
filename: str, optional

The name of the exported file

get_block_series()[source]

Ordered list of circuit blocks, including layer repetitions, from first applied to last applied.

get_final_state(angles)[source]

Evaluate the circuit by specifying each circuit parameter

Parameters
angles: list of float

A list of dimension (n,) for n free parameters in the circuit

Returns
final_state:obj:qutip.Qobj.

Final state of the circuit after evaluation

get_free_parameters_num()[source]

Compute the number of free parameters required to evaluate the circuit.

Returns
num_params: int

Number of free circuit parameters

get_initial_state()[source]
Returns
initial_state:obj:qutip.Qobj

Initial circuit state

get_unitary_products(propagators)[source]

Return two ordered lists of propagators in the circuit. Useful for modifying individual propagators and computing the product with these modifications. For example, to modify U_k in a product of N unitaries, one could take U_prods_back[N - 1 - k] * modified_U_k * U_prods[k]

Returns
U_prods: list ofobj:qutip.Qobj

Ordered list of [identity, U_0, U_1, … U_N]

U_prods_back: list ofobj:qutip.Qobj

Ordered list of [identity, U_N, U_{N-1}, … U_0]

optimize_parameters(initial='random', method='COBYLA', use_jac=False, layer_by_layer=False, bounds=None, constraints=())[source]

Run VQA optimization loop

Parameters
initial: str or list of floats, optional

Initialization method for the free parameters. If a list of floats of dimensions (n,) for n free parameters in the circuit is given, then these are taken to be the initial conditions for the optimizer. Otherwise if a string is given:

• (Default) “random” will randomize initial free parameters between 0 and 1.

• “ones” will set each initial free parameter to a value of 1.

method: str or callable, optional

Method to give to scipy.optimize.minimize

use_jac: bool, optional

Whether to compute the jacobian or not. If computed, it will be passed to the optimizer chosen by method, regardless of if the method is gradient-based or not. Note that derivatives of unitaries generated by ParameterizedHamiltonian are calculated with the Frechet derivative of the exponential function, using scipy.linalg.expm_frechet.

layer_by_layer: bool, optional

Grow the circuit from a single layer to VQA.num_layers. At each step, hold the parameters found for previous layers fixed.

bounds: sequence or scipy.optimize.Bounds, optional

Bounds to be passed to the optimizer. Either

1. Instance of scipy.optimize.Bounds

2. Sequence of (min, max) tuples corresponding to each free parameter.

constraints: list of Constraint

See scipy.optimize.minimize documentation.

Returns
result:obj:.OptimizationResult

The optimized angles and final state.

class qutip_qip.vqa.VQABlock(operator, is_unitary=False, name=None, targets=None, initial=False)[source]

Bases: object

Component of a VQA. Can return a unitary, and take derivatives of its own unitary. Forms a Gate in the QubitCircuit generated by the VQA.

Parameters
operator:obj:qutip.Qobj or Callable or str

If given as a qutip.Qobj, assumed to be a Hamiltonian with a single global parameter. If given as a Callable, assumed to take in a parameter, and return a unitary operator. If given as a str, assumed to reference a native QuTiP gate from qutip_qip.operations

is_unitary: bool, optional

Specifies that the operator was already in Unitary form, and does not need to be exponentiated, or take a parameter.

name: str, optional

Name of the block. This will be used in the custom user_gates dict of the circuit. If not provided, a name will be generated as “U”+str(len(VQA.blocks)).

targets: list of int, optional

The qubits targetted by the gate. By default, applied to all qubits.

initial: bool, optional

Whether or not to repeat this block in layers. For example, this should be True if this block is only used for circuit initialization.

get_unitary(angles=None)[source]

Return the block unitary.

Parameters
angles: list of float, optional

Block free parameters. Required if the block has free parameters.

get_unitary_derivative(angles, term_index=0)[source]

Compute the derivative of the block’s unitary with respect to its free parameter, assuming it is of the form $$e^{-i \theta H}$$ for a free parameter theta. If the block’s operator is a ParameterizedHamiltonian, use the Frechet derivative of the exponential function.

Parameters
angle: list of float

free parameters to take derivatives with respect to

term_index: int, optional

Index of Parameterized Hamiltonian term that specifies the matrix direction in which to take the derivative.

Returns
derivative: float