Source code for qplex.algorithms.vqe

import numpy as np

from qplex.algorithms.base_algorithm import Algorithm
import qplex


[docs] class VQE(Algorithm): """ Variational Quantum Eigensolver (VQE). This class implements the VQE algorithm for solving optimization problems using a variational approach. It creates a quantum circuit, updates parameters, and provides a starting point for the optimization. Attributes ---------- layers : int The number of layers in the VQE ansatz. n : int The number of qubits in the quantum circuit. circuit : str The OpenQASM3 representation of the VQE circuit. num_params : int The number of parameters for the VQE variational circuit. """ def __init__(self, model, layers: int, seed: int, penalty: float, ansatz: str): """ Initializes the VQE algorithm with the given parameters. Parameters ---------- model : QModel The optimization model to be solved. layers : int The number of layers in the VQE ansatz. seed : int The seed for the random number generator. penalty : float The penalty factor for the QUBO conversion. ansatz : str The ansatz type used in the VQE algorithm. """ super().__init__(model) self.layers: int = layers self.n: int = 0 self.num_params = None self.circuit: str = self.create_circuit(penalty=penalty) np.random.seed(seed)
[docs] def create_circuit(self, *args, **kwargs) -> str: """ Creates a quantum circuit in the form of an OpenQASM3 string for VQE. The circuit is constructed based on the QUBO encoding of the model, including all necessary gates for the VQE ansatz. Parameters ---------- kwargs Optional parameters, including 'penalty' for QUBO conversion. Returns ------- str An OpenQASM3 string representing the quantum circuit for VQE. """ self.qubo = self.model.get_qubo(penalty=kwargs['penalty']) self.n = self.qubo.get_num_binary_vars() self.num_params = self.n + (4 * (self.n - 1) * self.layers) circuit_lines = [f"input float[64] theta{i};" for i in range(self.num_params)] circuit_lines.extend([f"qreg q[{self.n}];", f"creg c[{self.n}];"]) pc = 0 circuit_lines.extend( [f"ry(param{pc + i}) q[{i}];" for i in range(self.n)]) pc += self.n for d in range(self.layers): for i in range(self.n - 1): circuit_lines.append(f"cx q[{i}], q[{i + 1}];") circuit_lines.append(f"ry(param{pc}) q[{i}];") pc += 1 circuit_lines.append(f"ry(param{pc}) q[{i + 1}];") pc += 1 circuit_lines.append(f"cx q[{i}], q[{i + 1}];") circuit_lines.append(f"ry(param{pc}) q[{i}];") pc += 1 circuit_lines.append(f"ry(param{pc}) q[{i + 1}];") pc += 1 circuit_lines.extend( [f"measure q[{i}] -> c[{i}];" for i in range(self.n)]) return "\n".join(circuit_lines)
[docs] def update_params(self, params: np.ndarray) -> str: """ Updates the parameters of the VQE circuit. The circuit is updated by replacing the placeholder angles with the values provided in the parameter array. Parameters ---------- params : np.ndarray The new set of parameters for the VQE circuit. Returns ------- str The updated OpenQASM3 string for the VQE circuit. """ return qplex.utils.circuit_utils.replace_params(self.circuit, params)
[docs] def get_starting_point(self) -> np.ndarray: """ Defines the starting point for the VQE optimization. Returns ------- np.ndarray An array representing the starting point for VQE, initialized with random values. """ return np.random.rand(self.n + (4 * (self.n - 1) * self.layers))