This is a package accompanying the paper Exploiting In-Constraint Energy in Constrained Variational Quantum Optimization. QVoice runs variational quantum algorithms with in-constraint energy, an alternative objective for constrained problems, to achieve higher accuracies and lower numbers of iterations in comparison to using energy (exepectation value of the Hamiltonian) as the objective.
git clone https://github.com/haoty/QVoice.git
pip install -e ./QVoice
import qvoice
from qiskit_aer import AerSimulator
from qiskit.algorithms import QAOA
from qiskit.algorithms.optimizers import COBYLA
problem = qvoice.problems.clique.get_random_instance(num_var=8, seed=42)
algorithm = QAOA(optimizer=COBYLA(), quantum_instance=AerSimulator(method="statevector"))
result = qvoice.InConstraintSolver(algorithm, problem).solve()
The following walkthrough is also available in the format of Jupyter notebook and Python script.
First, set the number of variables/qubits and the seed for generating the problem
n = 10
seed = 42
Define a problem with qiskit_optimization
, qiskit_finance
, or docplex.mp
import networkx as nx
from qiskit_optimization.applications import GraphPartition
problem = GraphPartition(
nx.random_partition_graph([n // 2] * 2, 1, 2 / n, seed)
).to_quadratic_program()
# from qiskit_finance.applications.optimization import PortfolioOptimization
# problem = PortfolioOptimization(...).to_quadratic_program()
Or even easier, get a random instance of a supported problem from qvoice.problems
from qvoice.problems import (
portfolio_optimization,
vertex_cover,
clique,
graph_partition,
independent_set,
max_bisection
)
problem = portfolio_optimization.get_random_instance(n, seed)
Print out the problem formulation
print(problem.prettyprint())
Define the VQA algorithm with qiskit
as usual
import qvoice
from qiskit_aer import AerSimulator
from qiskit.algorithms import VQE, QAOA
from qiskit.algorithms.optimizers import COBYLA
from qiskit.circuit.library import TwoLocal
reps = 1
maxiter = 300
optimizer = COBYLA(maxiter=maxiter, disp=True)
backend = AerSimulator(method="statevector")
algorithm = VQE(
TwoLocal(n, "ry", "cz", reps=reps, entanglement="linear"),
optimizer=optimizer,
quantum_instance=backend,
)
# or
algorithm = QAOA(
reps=1,
optimizer=optimizer,
quantum_instance=backend,
)
The InConstraintSolver
can be constructed with one line of code using normal qiskit
problem and VQA objects
solver = qvoice.InConstraintSolver(algorithm, problem)
It also can be fine-tuned with several options.
in_cons_prob_lbound
specifies the lower bound constraint for the in-constraint probability. Default isNone
.penalty
defines the penalty factor that controls the penalty term in the Hamiltonian. Default isNone
, which usesqiskit_optimization
's penalty heuristic:qiskit_optimization.converters.LinearEqualityToPenalty()._auto_define_penalty(problem)
.use_in_cons_energy
can be set toFalse
to use the normal penalized energy approach while still having metrics logged during the optimization process. Default isTrue
.log_level
tells the solver what metrics to compute and log at each iteration. Higherlog_level
gives more information but also leads to greater overheads. Note that for some solver settings, certain metrics need to be computed regardless of howlog_level
specifies. Default is 0.log_level=0
Nothinglog_level=1
energylog_level=2
in-constraint probabilitylog_level=3
approximation ratio and optimal solution probability
in_cons_prob_lbound = 0.05
penalty = None
solver = qvoice.InConstraintSolver(
algorithm,
problem,
penalty=penalty,
use_in_cons_energy=True,
in_cons_prob_lbound=in_cons_prob_lbound,
log_level=3,
)
print(solver.solve())
Plot the logged metrics and the grid search overlaid with the optimizer trace.
solver.plot_log()
beta_steps, gamma_steps = 30, 30
solver.plot_pareto_frontier(
beta_steps=beta_steps,
gamma_steps=gamma_steps,
)
- Refactor to support custom objectives and constraints
- Support lazy evaluation of function values.
- Integrate into Qiskit