Programes Variacionals
El funcional VariationalProgram reuneix les peces necessàries per a un algorisme quàntic variacional. Accepta un funcional primitiu parametritzat, un optimitzador i una funció de cost. Quan s’invoca execute(), avalua el funcional repetidament amb paràmetres actualitzats, introdueix el FunctionalResult resultant a la funció de cost subministrada i finalment retorna un VariationalProgramResult. Les restriccions de paràmetres (desigualtats/igualtats sobre paràmetres) s’adjunten a aquest nivell mitjançant l’argument parameter_constraints; aquest és el lloc per fer complir relacions com theta >= phi o límits entre paràmetres a tots els funcionals de QiliSDK. Només els paràmetres marcats com a entrenables s’optimitzen durant aquest bucle.
Paràmetres
functional (
PrimitiveFunctional): Primitiu parametritzat a optimitzar (per exempleDigitalPropagationoAnalogEvolution).optimizer (
Optimizer): Optimitzador clàssic que proposa nous valors de paràmetres i opcionalment emmagatzema iterats intermedis.cost_function (
CostFunction): Objecte que mapeja els resultats funcionals a un cost escalar; freqüentment construït a partir d’unModel.store_intermediate_results (bool, opcional): Quan és True, l’optimitzador conserva els passos intermedis, que s’exposen mitjançant
intermediate_results.parameter_constraints (list[
ComparisonTerm], opcional): Restriccions sobre els paràmetres funcionals (p. ex.,theta >= 0.5) avaluades abans de cada actualització de l’optimitzador. Aquest és el punt d’entrada admès per fer complir les relacions entre paràmetres a QiliSDK.
Retorna
VariationalProgramResult: Recupereuoptimal_cost,optimal_parametersi la sortida funcional final empaquetada enoptimal_execution_results.
Exemple d’ús (fent servir el backend QiliSim)
import numpy as np
from qilisdk.backends import QiliSim
from qilisdk.core.model import Model, ObjectiveSense
from qilisdk.core.variables import LEQ, BinaryVariable
from qilisdk.cost_functions.model_cost_function import ModelCostFunction
from qilisdk.digital import CNOT, U3, HardwareEfficientAnsatz
from qilisdk.functionals import DigitalPropagation
from qilisdk.functionals.variational_program import VariationalProgram
from qilisdk.optimizers.scipy_optimizer import SciPyOptimizer
from qilisdk.readout import Readout
values = [2, 3, 7]
weights = [1, 3, 3]
max_weight = 4
binary_var = [BinaryVariable(f"b{i}") for i in range(len(values))]
model = Model("Knapsack")
model.set_objective(sum(binary_var[i] * values[i] for i in range(len(values))), sense=ObjectiveSense.MAXIMIZE)
model.add_constraint("max_weights", LEQ(sum(binary_var[i] * weights[i] for i in range(len(weights))), max_weight))
ansatz = HardwareEfficientAnsatz(
nqubits=3, layers=4, connectivity="Circular", one_qubit_gate=U3, two_qubit_gate=CNOT, structure="Interposed"
)
optimizer = SciPyOptimizer(method="COBYQA")
backend = QiliSim()
result = backend.execute(
VariationalProgram(
functional=DigitalPropagation(ansatz),
optimizer=optimizer,
cost_function=ModelCostFunction(model),
),
Readout().with_sampling(nshots=1000),
)
print(result)
Sortida
VariationalProgramResult(
Optimal Cost=-9.0,
Optimal Parameters=[...],
Intermediate Results=[...],
Optimal Results=- Functional Results: [
Sampling Results: (
nshots=1000,
samples={'000': 2, '010': 3, '101': 994, '110': 1}
)
]
)
Exemple d’ús 2 (fent servir el backend QiliSim) Aquest exemple optimitza un esquema variacional sota algunes restriccions de paràmetres.
from qilisdk.core.variables import LT, GreaterThan
from qilisdk.cost_functions.observable_cost_function import ObservableCostFunction
from qilisdk.functionals import VariationalProgram, AnalogEvolution
from qilisdk.optimizers.scipy_optimizer import SciPyOptimizer
from qilisdk.analog import *
from qilisdk.analog.schedule import Interpolation
from qilisdk.core.variables import Parameter
from qilisdk.core import ket, tensor_prod
from qilisdk.backends import QiliSim
from qilisdk.readout import Readout
import numpy as np
from qilisdk.utils.visualization.style import ScheduleStyle
T = 10
p = [Parameter(f"p_{i}", (i + 1)*2, bounds=(0, 10)) for i in range(4)]
p.insert(0, 0)
p.append(T)
s = [Parameter(f"s_{i}", (i + 2) * 0.1, bounds=(0, 1)) for i in range(2)]
h0 = X(0)
h1 = Z(0)
max_time = Parameter("max_time", 1.5)
schedule = Schedule(
hamiltonians={"h_x": h0, "h_z": h1},
coefficients={
"h_x": {p[0]: 1, (p[1], p[2]): 1 - s[0], (p[3], p[4]): 1 - s[1], p[5]: 0},
"h_z": {p[0]: 0, (p[1], p[2]): s[0], (p[3], p[4]): s[1], p[5]: 1},
},
interpolation=Interpolation.LINEAR,
)
schedule.draw(ScheduleStyle(title="Schedule Before Optimization"))
te = AnalogEvolution(
schedule=schedule,
initial_state=tensor_prod([ket(0) - ket(1) for _ in range(schedule.nqubits)]).unit(),
)
vp = VariationalProgram(
te,
SciPyOptimizer(method="COBYQA"),
cost_function=ObservableCostFunction(h1),
parameter_constraints=[
GreaterThan(p[3], 5)
]
)
print(vp.get_constraints()) # print the constraints of the variational program.
backend = QiliSim()
results = backend.execute(vp, Readout().with_expectation(observables=[h1]).with_state_tomography().with_sampling(nshots=1000))
schedule.draw(ScheduleStyle(title="Schedule After Optimization"))
print(results)