This tutorial shows how to place simple bounds on the values of a model's parameters. This can be especially useful when building your own objects (see the custom operator tutorial) that might have restrictions on their allowed parameters.
First, we construct a model. It doesn't really matter what type of model this is, as the procedure we outline below is the same regardless of the model type. We choose to create a simple 1-qubit model.
import pygsti
from pygsti.modelpacks import smq1Q_XYI
mdl = smq1Q_XYI.target_model("H+S")
Next, we choose which parameter(s) to add bounds for. Let's suppose that we want to restrict the Hamiltonian (coherent) Z error rate on the $X(\pi/2)$ gate to be between 0 and 0.2, restricting the gate error to being over-rotation of magnitude at most 0.2 radians. First, let's find the modelmember and parameter value we want to bound.
# Here's the X(pi/2) gate:
print(mdl.operations[('Gxpi2', 0)])
# this is the error generator whose parameters we want to bound
eg = mdl.operations[('Gxpi2', 0)].factorops[1].errorgen
for i, lbl in enumerate(eg.parameter_labels):
print(i, lbl)
This shows us that we want to set bounds for the parameter with index 2. Currently the bounds are set to None
, which means there aren't any:
print(eg.parameter_bounds)
We can set the parameter_bounds
attribute of a model member to be a 2D NumPy array of shape (num_params, 2), that has rows equal to (min, max) values for each parameter. We can use numpy.inf
and -numpy.inf
for parameters where we don't want one or both bounds.
import numpy as np
bounds = np.empty((eg.num_params, 2), 'd')
bounds[:, 0] = -np.inf # initial lower bounds
bounds[:, 1] = np.inf # initial upper bounds
bounds[2, :] = (0, 0.2) # bounds for "Z Hamiltonian error coefficient" parameter
eg.parameter_bounds = bounds
After we've set the bounds on constituent members, we should retrieve the model's number of parameters (.num_params
) to ensure that the bounds get propagated throughout the model:
print("Model bounds before getting the number of parameters:\n",mdl.parameter_bounds)
mdl.num_params # triggers re-building of model's parameters and parameter bounds based on its members.
print("\nModel bounds after getting the number of parameters:\n",mdl.parameter_bounds)
Now, when model mdl
is optimized, the optimizer will limit range of this parameter as desired.