Gates
The state of a quantum system is modified by means of quantum gates.
Constructing gates
DQCsim provides four types of gates.
- Unitary gates: these apply a gate matrix on one or more qubits.
- Measurement gates: these cause the state of a qubit to be collapsed along and measured in some basis.
- Prep gates: these set the state of a qubit to some value.
- Custom gates: anything else that the downstream plugin supports.
These are constructed using the following functions. The predefined gates are as described earlier.
dqcs_gate_new_predef()
Constructs a new predefined unitary gate.
Constructs a new predefined unitary gate.
dqcs_handle_t dqcs_gate_new_predef(
dqcs_predefined_gate_t gate_type,
dqcs_handle_t qubits,
dqcs_handle_t param_data
)
gate_type
specifies which kind of gate should be constructed.
targets
must be a handle to a non-empty qubit set, containing at least
as many qubits as needed for the specified gate type. If more qubits are
specified, the rightmost qubits become the targets, and the remaining
qubits become control qubits to make a controlled gate.
param_data
takes an optional ArbData
object used to parameterize the
gate if necessary. If not specified, an empty object is used. Some of the
gate types are parameterized, and use values from this ArbData
as
defined in the docs for dqcs_predefined_gate_t
. Anything remaining in
the ArbData
afterwards is placed in the gate object.
This function returns the handle to the gate, or 0 to indicate failure. The qubit set and parameterization data (if specified) are consumed/deleted by this function if and only if it succeeds.
dqcs_gate_new_predef_one()
Constructs a new predefined unitary one-qubit gate.
Constructs a new predefined unitary one-qubit gate.
dqcs_handle_t dqcs_gate_new_predef_one(
dqcs_predefined_gate_t gate_type,
dqcs_qubit_t qa,
dqcs_handle_t param_data
)
This function is simply a shorthand for dqcs_gate_new_predef()
with
one qubit in the qubits
set, to make constructing one-qubit gates more
ergonomic. Refer to its documentation for more information.
dqcs_gate_new_predef_two()
Constructs a new predefined unitary two-qubit gate.
Constructs a new predefined unitary two-qubit gate.
dqcs_handle_t dqcs_gate_new_predef_two(
dqcs_predefined_gate_t gate_type,
dqcs_qubit_t qa,
dqcs_qubit_t qb,
dqcs_handle_t param_data
)
This function is simply a shorthand for dqcs_gate_new_predef()
with
two qubit in the qubits
set, to make constructing two-qubit gates more
ergonomic. Refer to its documentation for more information.
dqcs_gate_new_predef_three()
Constructs a new predefined unitary three-qubit gate.
Constructs a new predefined unitary three-qubit gate.
dqcs_handle_t dqcs_gate_new_predef_three(
dqcs_predefined_gate_t gate_type,
dqcs_qubit_t qa,
dqcs_qubit_t qb,
dqcs_qubit_t qc,
dqcs_handle_t param_data
)
This function is simply a shorthand for dqcs_gate_new_predef()
with
three qubit in the qubits
set, to make constructing three-qubit gates
more ergonomic. Refer to its documentation for more information.
dqcs_gate_new_unitary()
Constructs a new unitary gate.
Constructs a new unitary gate.
dqcs_handle_t dqcs_gate_new_unitary(
dqcs_handle_t targets,
dqcs_handle_t controls,
dqcs_handle_t matrix
)
targets
must be a handle to a non-empty qubit set. The qubits in this set
correspond with the supplied unitary matrix.
controls
optionally specifies a set of control qubits. You may pass 0 or
an empty qubit set if you don't need control qubits.
matrix
must be a handle to an appropriately sized matrix.
The supplied matrix is only applied to the target qubits if all the control qubits are or will be determined to be set. For instance, to encode a CCNOT/Toffoli gate, you can specify one target qubits, two control qubits, and [0, 1; 1, 0] (X) for the matrix. This is equivalent to extending the matrix to the full Toffoli matrix and specifying all three qubits in the targets set, or the midway solution using a CNOT matrix, but these solutions may be less efficient depending on whether the simulator can optimize its calculations for controlled gates.
Simulators are not required to apply the (hidden) global phase component of the gate matrix in the same way it is specified; that is, if the simulator can optimize its calculations by altering the global phase it is allowed to.
DQCsim checks whether the matrix is unitary using the equivalent of
dqcs_mat_approx_unitary()
with an epsilon value of 1e-6.
This function returns the handle to the gate, or 0 to indicate failure.
The targets
qubit set, (if specified) the controls
qubit set, and the
matrix are consumed/deleted by this function if and only if it succeeds.
dqcs_gate_new_measurement()
Constructs a new measurement gate.
Constructs a new measurement gate.
dqcs_handle_t dqcs_gate_new_measurement(
dqcs_handle_t measures,
dqcs_handle_t matrix
)
measures
must be a handle to a qubit set. matrix
is an optional matrix
handle signifying the measurement basis. If zero, the Z basis is used.
Otherwise, it must be a handle to a unitary 2x2 matrix, and the semantics
of the measurement are as follows:
- apply the hermetian of the matrix to each qubit
- measure each qubit in the Z basis
- apply the matrix to each qubit
This function returns the handle to the gate, or 0 to indicate failure.
The measures
qubit set and matrix
handle are consumed/deleted by this
function if and only if it succeeds.
dqcs_gate_new_prep()
Constructs a new prep gate.
Constructs a new prep gate.
dqcs_handle_t dqcs_gate_new_prep(
dqcs_handle_t targets,
dqcs_handle_t matrix
)
targets
must be a handle to a qubit set. matrix
is an optional matrix
handle signifying the state that the qubits are initialized to. If zero,
the qubits are initialized to |0>. Otherwise, it must be a handle to a
unitary 2x2 matrix, and the semantics are as follows:
- initialize each qubit to |0>
- apply the matrix to each qubit
This function returns the handle to the gate, or 0 to indicate failure.
The targets
qubit set and matrix
handle are consumed/deleted by this
function if and only if it succeeds.
dqcs_gate_new_custom()
Constructs a new custom gate.
Constructs a new custom gate.
dqcs_handle_t dqcs_gate_new_custom(
const char *name,
dqcs_handle_t targets,
dqcs_handle_t controls,
dqcs_handle_t measures,
dqcs_handle_t matrix
)
The functionality of custom gates is not specified by DQCsim. Instead, this is left up to the plugins. Of course, for this to work, plugins that are connected to each other must agree on the format used.
name
specifies the name of the gate. The name is used to indicate which
custom operation is to be applied.
targets
optionally specifies the set of target qubits. You may pass 0 or
an empty qubit set if you don't need target qubits.
controls
optionally specifies the set of control qubits. You may pass 0
or an empty qubit set if you don't need control qubits.
measures
optionally specifies the set of measured qubits. You may pass 0
or an empty qubit set if no qubits are measured. Note that the upstream
plugin expects exactly one measurement result for each qubit specified in
this set; anything else results in a warning and the measurement result
being set to undefined.
matrix
optionally specifies a handle to an appropriately sized matrix
for the targets
qubit set.
In addition to the above data, gate objects implement the arb
interface
to allow user-specified classical information to be attached.
This function returns the handle to the gate, or 0 to indicate failure. The specified qubit sets are consumed/deleted by this function if and only if it succeeds.
Control qubit representation
A gatestream source is allowed to specify controlled gates either using DQCsim's separate list of control qubits (this is the recommended way), by using an explicitly controlled gate matrix and using only the target qubit list, or a even mix of the two. The following two functions, primarily intended for gatestream sinks, can be used to convert between these representations.
dqcs_gate_reduce_control()
Utility function that detects control qubits in the targets
list of the
gate by means of the gate matrix, and reduces them into controls
qubits.
Utility function that detects control qubits in the targets
list of the
gate by means of the gate matrix, and reduces them into controls
qubits.
dqcs_handle_t dqcs_gate_reduce_control(
dqcs_handle_t gate,
double epsilon,
bool ignore_gphase
)
This function borrows a handle to any gate with a matrix, and returns an
equivalent copy of said gate with any control qubits in the targets
set
moved to the controls
set. The associated gate matrix is accordingly
reduced in size. The control qubits are added at the end of the controls
set in the same order they appeared in the targets
qubit set.
epsilon
specifies the maximum element-wise deviation from the identity
matrix for the relevant array elements for a qubit to be considered a
control qubit. Note that if this is greater than zero, the resulting gate
may not be exactly equivalent. If ignore_gphase
is set, any global phase
in the matrix is ignored, but the global phase of the non-control submatrix
is not changed.
This function returns a new gate handle with the modified gate, or a copy of the input gate if the matrix could not be reduced. If the input gate does not have a matrix (measurement gate, or custom gate without matrix) an error is returned instead.
dqcs_gate_expand_control()
Utility function that expands a gate matrix to account for all control
qubits.
Utility function that expands a gate matrix to account for all control qubits.
dqcs_handle_t dqcs_gate_expand_control(dqcs_handle_t gate)
This function borrows a handle to any gate with a matrix, and returns an
equivalent copy of said gate with any control qubits in the controls
set
moved to the targets
set. The associated gate matrix is extended
accordingly. The control qubits are added at the front of the targets
set in the same order they appeared in the controls
qubit set.
This function returns a new gate handle with the modified gate, or a copy of the input gate if the matrix could not be reduced. If the input gate does not have a matrix (measurement gate, or custom gate without matrix) an error is returned instead.
Attached classical data
Classical information can be attached to any gate using the ArbData
protocol: gate handles support all the dqcs_arb_*()
API calls. This is
primarily intended for custom gates.
Interpreting gates
DQCsim provides two ways for interpreting incoming gates: manually querying the parameters and gate maps. The latter is quite advanced and deserves its own section (the next one), but let's deal with the manual method first.
The first step for any incoming gate is to query its type.
dqcs_gate_type()
Returns the gate type of the given gate.
Returns the gate type of the given gate.
dqcs_gate_type_t dqcs_gate_type(dqcs_handle_t gate)
Returns DQCS_GATE_TYPE_INVALID if the gate handle is invalid.
This results in the following enumeration. The exact semantics of each type of gate is listed in the documentation of each enum variant.
dqcs_gate_type_t
Types of DQCsim gates.
Types of DQCsim gates.
typedef enum { ... } dqcs_gate_type_t;
Variants:
The semantics are that the unitary matrix expanded by the number of
control qubits is applied to the qubits. The data field may add pragma-like hints to the gate, for instance to
represent the line number in the source file that generated the gate,
error modelling information, and so on. This data may be silently
ignored. The semantics are: This allows any measurement basis to be used. The data field may add pragma-like hints to the gate, for instance to
represent the line number in the source file that generated the gate,
error modelling information, and so on. This data may be silently
ignored. The semantics are: This allows any initial state to be used. The data field may add pragma-like hints to the gate, for instance to
represent the line number in the source file that generated the gate,
error modelling information, and so on. This data may be silently
ignored. The semantics are:DQCS_GATE_TYPE_INVALID = 0
DQCS_GATE_TYPE_UNITARY
DQCS_GATE_TYPE_MEASUREMENT
DQCS_GATE_TYPE_PREP
DQCS_GATE_TYPE_CUSTOM
The following functions can be used to read the remaining parameters associated with a gate.
dqcs_gate_has_targets()
Returns whether the specified gate has target qubits.
Returns whether the specified gate has target qubits.
dqcs_bool_return_t dqcs_gate_has_targets(dqcs_handle_t gate)
dqcs_gate_targets()
Returns a handle to a new qubit reference set containing the qubits
targeted by this gate.
Returns a handle to a new qubit reference set containing the qubits targeted by this gate.
dqcs_handle_t dqcs_gate_targets(dqcs_handle_t gate)
dqcs_gate_has_controls()
Returns whether the specified gate has control qubits.
Returns whether the specified gate has control qubits.
dqcs_bool_return_t dqcs_gate_has_controls(dqcs_handle_t gate)
dqcs_gate_controls()
Returns a handle to a new qubit reference set containing the qubits
that control this gate.
Returns a handle to a new qubit reference set containing the qubits that control this gate.
dqcs_handle_t dqcs_gate_controls(dqcs_handle_t gate)
dqcs_gate_has_measures()
Returns whether the specified gate measures any qubits.
Returns whether the specified gate measures any qubits.
dqcs_bool_return_t dqcs_gate_has_measures(dqcs_handle_t gate)
dqcs_gate_measures()
Returns a handle to a new qubit reference set containing the qubits
measured by this gate.
Returns a handle to a new qubit reference set containing the qubits measured by this gate.
dqcs_handle_t dqcs_gate_measures(dqcs_handle_t gate)
dqcs_gate_has_matrix()
Returns whether a unitary matrix is associated with this gate.
Returns whether a unitary matrix is associated with this gate.
dqcs_bool_return_t dqcs_gate_has_matrix(dqcs_handle_t gate)
dqcs_gate_matrix()
Returns a copy of the unitary matrix associated with this gate, if one
exists.
Returns a copy of the unitary matrix associated with this gate, if one exists.
dqcs_handle_t dqcs_gate_matrix(dqcs_handle_t gate)
If this function succeeds, a new matrix handle is returned. If it fails, 0 is returned.
dqcs_gate_has_name()
Returns whether the specified gate has a name.
Returns whether the specified gate has a name.
dqcs_bool_return_t dqcs_gate_has_name(dqcs_handle_t gate)
dqcs_gate_name()
Returns the name of a custom gate.
Returns the name of a custom gate.
char *dqcs_gate_name(dqcs_handle_t gate)
This function fails if the gate is not a custom gate. Query
dqcs_gate_has_name()
to disambiguate between a non-custom gate and a
different error.
On success, this returns a newly allocated string containing the gate
name. Free it with free()
when you're done with it to avoid memory
leaks. On failure, this returns NULL
.