User Defined Ansatz¶
Here we present how a combinatorial optimization problem can be solved within the VQE method and a user-defined ansatz. This method enrich the platform defined ansatze: QAOAPenalty and QAOAMixer.
Lets demonstrate on the Max Vertex Cover (MVC) problem, which is described in problem library.
import networkx as nx import pyomo.core as pyo def mvc(graph: nx.Graph, k: int) -> pyo.ConcreteModel: model = pyo.ConcreteModel() model.x = pyo.Var(graph.nodes, domain=pyo.Binary) model.amount_constraint = pyo.Constraint(expr=sum(model.x.values()) == k) def obj_expression(model): # number of edges not covered return sum((1 - model.x[i]) * (1 - model.x[j]) for i, j in graph.edges) model.cost = pyo.Objective(rule=obj_expression, sense=pyo.minimize) return model mvc_model = mvc(graph=nx.star_graph(4), k=1)
Initializing the ansatz¶
Here, we define our ansatz. It consists from a Hardware efficient ansatz function
from classiq import Model from classiq.builtin_functions import HardwareEfficientAnsatz model = Model() model.HardwareEfficientAnsatz(HardwareEfficientAnsatz(num_qubits=5, reps=1)) ansatz = model.synthesize()
Now we connect all the components using
CombinatorialOptimization class and send a
QSolver for this case is
from classiq.applications.combinatorial_optimization import ( CombinatorialOptimization, QAOAPreferences, QSolver, ) problem = CombinatorialOptimization( model=mvc_model, qsolver_preferences=QAOAPreferences(qsolver=QSolver.Custom), ansatz=ansatz, ) result = problem.solve()
Changing the ansatz¶
Another option is to initialize
CombinatorialOptimization class with a builtin
QSolver and then change
it to a custom ansatz.
problem = CombinatorialOptimization( model=mvc_model, qsolver_preferences=QAOAPreferences(qsolver=QSolver.QAOAPenalty), ) problem.ansatz = ansatz result = problem.solve()
Checking solutions validity¶
QAOAMixer is an example for an ansatz which assures that all the resulting solutions are valid under the problem's constraints. The user defined ansatz may have this quality, or not.
CombinatorialOptimization lets the user to declare if the ansatz is "constraints-preserving", and will act accordingly.
Namely, for those ansatze (e.g. QAOAMixer), we will check if all the solutions are valid.
This attribute is defined using
The default value of
should_check_valid_solutions field is set to
True only for
QSolve.QAOAMixer and for a
quantum backend which is an exact simulator. If the backend is noisy we cannot completely assure the solutions validity.
So, for example, if we first use
QAOAMixer and then switch to a user-defined ansatz which doesn't
preserve the constraints, we have to explicitly switch off the
problem = CombinatorialOptimization( model=mvc_model, qsolver_preferences=QAOAPreferences(qsolver=QSolver.QAOAMixer), ) problem.should_check_valid_solutions = False problem.ansatz = ansatz result = problem.solve()
Setting and getting the model¶
Custom ansatz can be defined by supplying the
model to the
Similar to the previously described method using
problem = CombinatorialOptimization( model=mvc_model, qsolver_preferences=QAOAPreferences(qsolver=QSolver.Custom), ) problem.model = model result = problem.solve()
Note that while using QSolver.Custom, the field 'model' will not exist unless the user explicitly sets it.