Masking Circuits¶
The concept of masking is fairly simple: When a position in a mask is set to True, the object referenced will not appear when the mask is applied. In our case referenced objects are gates in a quantum circuit that can be removed by applying masks.
When considering different ansätze from literature, e.g. when creating parameterised
quantum circuits that often rely on repeating layers, it becomes clear that a single
mask cannot be easily used while still maintaining comprehensability, usability, and
maintainability. We use a composition of masks instead to create the concept of a
MaskedCircuit
.
A MaskedCircuit
has a concept of wires, layers as well as
entangling gates that make up the variational part of the circuit.
Each of them is represented by a separate Mask
. The final mask that is
applied to the underlying parameters is the intersection of all masks.
You can change and adapt masks by different methods:
you can manually set specific positions in a mask,
you can perturb a mask on a random position, and
you can shrink a mask.
- class maskit.masks.PerturbationAxis(value)¶
An enumeration.
- LAYERS = 1¶
Perturbation affects whole layers
- RANDOM = 2¶
Perturbation affects random locations in parameter mask
- WIRES = 0¶
Perturbation affects whole wires
- class maskit.masks.PerturbationMode(value)¶
An enumeration.
- ADD = 0¶
Adding new holes to the mask
- INVERT = 2¶
Invert current state of the mask
- REMOVE = 1¶
Removing holes from the mask
- class maskit.masks.MaskedCircuit(parameters: ndarray, layers: int, wires: int, dynamic_parameters: bool = True, default_value: Optional[float] = None, parameter_mask: Optional[ndarray] = None, layer_mask: Optional[ndarray] = None, wire_mask: Optional[ndarray] = None)¶
A MaskedCircuit supports masking of different components including wires, layers, and parameters. Masking naturally removes active parameters from a circuit. However, some optimisers expect the array of parameters to remain stable across iteration steps; use
dynamic_parameters=False
to force the mask to always yield the full set of parameters in such cases. The mask will still prevent modification of inactive parameters.- Parameters:
parameters – Initial parameter set for circuit
layers – Number of layers
wires – Number of wires
dynamic_parameters – Whether the array of differentiable parameters may change size/order
default_value – Default value for gates that are added back in. In case of None that is also the default, the last known value is assumed
parameter_mask – Initialization values of paramater mask, defaults to None
layer_mask – Initialization values of layer mask, defaults to None
wire_mask – Initialization values of wire mask, defaults to None
- MaskedCircuit.perturb(axis: PerturbationAxis = PerturbationAxis.RANDOM, amount: Optional[Union[int, float]] = None, mode: PerturbationMode = PerturbationMode.INVERT)¶
Perturbs the MaskedCircuit for a given
axis
that is of typePerturbationAxis
. The perturbation is appliedamount
times and depends on the givenmode
of typePerturbationMode
. If no amount is given, that isamount=None
, a randomamount
is determined given by the actual size of the py:attr:~.mask. Theamount
is automatically limited to the actual size of the py:attr:~.mask.- Parameters:
amount – Number of items to perturb, defaults to None
axis – Which mask to perturb
mode – How to perturb, defaults to PerturbationMode.INVERT
- Raises:
NotImplementedError – Raised in case of an unknown mode
- MaskedCircuit.shrink(axis: PerturbationAxis = PerturbationAxis.LAYERS, amount: int = 1)¶