Reference

This chapter simply lists all API functions and types ordered by name.

dqcs_arb_assign()

Copies the data from one object to another.

dqcs_return_t dqcs_arb_assign(
    dqcs_handle_t dest,
    dqcs_handle_t src
)
dqcs_arb_cbor_get()

Returns the JSON/CBOR object of an ArbData object in the form of a CBOR object.

ssize_t dqcs_arb_cbor_get(
    dqcs_handle_t arb,
    void *obj,
    size_t obj_size
)

If the actual size of the object differs from the specified object size, this function will copy the minimum of the actual and specified sizes number of bytes, and return what the actual size was.

If the specified object size is zero, obj is allowed to be NULL. You can use this to query the size before allocating an object.

This function returns -1 on failure.

dqcs_arb_cbor_set()

Sets the JSON/CBOR object of an ArbData object by means of a CBOR object.

dqcs_return_t dqcs_arb_cbor_set(
    dqcs_handle_t arb,
    const void *obj,
    size_t obj_size
)
dqcs_arb_clear()

Clears the unstructured argument list.

dqcs_return_t dqcs_arb_clear(dqcs_handle_t arb)
dqcs_arb_get_raw()

Returns the unstructured string argument at the specified index.

ssize_t dqcs_arb_get_raw(
    dqcs_handle_t arb,
    ssize_t index,
    void *obj,
    size_t obj_size
)

If the actual size of the object differs from the specified object size, this function will copy the minimum of the actual and specified sizes number of bytes, and return what the actual size was.

If the specified object size is zero, obj is allowed to be NULL. You can use this to determine the size of the argument prior to actually reading it, so you can allocate the right buffer size first.

This function returns -1 on failure.

dqcs_arb_get_size()

Returns the size in bytes of the unstructured string argument at the specified index.

ssize_t dqcs_arb_get_size(
    dqcs_handle_t arb,
    ssize_t index
)

Returns -1 when the function fails.

dqcs_arb_get_str()

Returns the unstructured string argument at the specified index.

char *dqcs_arb_get_str(
    dqcs_handle_t arb,
    ssize_t index
)

On success, this returns a newly allocated string containing the JSON string. Free it with free() when you're done with it to avoid memory leaks. On failure, this returns NULL.

dqcs_arb_insert_raw()

Inserts an unstructured raw argument into the list at the specified index.

dqcs_return_t dqcs_arb_insert_raw(
    dqcs_handle_t arb,
    ssize_t index,
    const void *obj,
    size_t obj_size
)
dqcs_arb_insert_str()

Inserts an unstructured string argument into the list at the specified index.

dqcs_return_t dqcs_arb_insert_str(
    dqcs_handle_t arb,
    ssize_t index,
    const char *s
)
dqcs_arb_json_get()

Returns the JSON/CBOR object of an ArbData object in the form of a JSON string.

char *dqcs_arb_json_get(dqcs_handle_t arb)

On success, this returns a newly allocated string containing the JSON string. Free it with free() when you're done with it to avoid memory leaks. On failure, this returns NULL.

dqcs_arb_json_set()

Sets the JSON/CBOR object of an ArbData object by means of a JSON string.

dqcs_return_t dqcs_arb_json_set(
    dqcs_handle_t arb,
    const char *json
)
dqcs_arb_len()

Returns the number of unstructured arguments, or -1 to indicate failure.

ssize_t dqcs_arb_len(dqcs_handle_t arb)
dqcs_arb_new()

Creates a new ArbData object.

dqcs_handle_t dqcs_arb_new(void)

Returns the handle of the newly created ArbData. The ArbData is initialized with JSON object {} and an empty binary argument list.

ArbData objects support the handle and arb APIs.

dqcs_arb_pop()

Pops an unstructured argument from the back of the list without returning it.

dqcs_return_t dqcs_arb_pop(dqcs_handle_t arb)
dqcs_arb_pop_raw()

Pops an unstructured raw argument from the back of the list.

ssize_t dqcs_arb_pop_raw(
    dqcs_handle_t arb,
    void *obj,
    size_t obj_size
)

If the actual size of the object differs from the specified object size, this function will copy the minimum of the actual and specified sizes number of bytes, and return what the actual size was.

If the specified object size is zero, obj is allowed to be NULL. You can use this if you don't need the contents of the argument and just want to delete it.

Since this function removes the returned element, data will be lost if the specified size is smaller than the actual size. To avoid this, first use dqcs_arb_get_size(handle, -1) to query the size.

This function returns -1 on failure. If this is due to a NULL buffer being passed, the data that was popped is lost.

dqcs_arb_pop_str()

Pops an unstructured string argument from the back of the list.

char *dqcs_arb_pop_str(dqcs_handle_t arb)

On success, this returns a newly allocated string containing the JSON string. Free it with free() when you're done with it to avoid memory leaks. On failure, this returns NULL. If the failure is due to the conversion from binary object to C string (i.e., embedded nulls), the data is still popped and is thus lost.

dqcs_arb_push_raw()

Pushes an unstructured raw argument to the back of the list.

dqcs_return_t dqcs_arb_push_raw(
    dqcs_handle_t arb,
    const void *obj,
    size_t obj_size
)
dqcs_arb_push_str()

Pushes an unstructured string argument to the back of the list.

dqcs_return_t dqcs_arb_push_str(
    dqcs_handle_t arb,
    const char *s
)
dqcs_arb_remove()

Removes the specified unstructured string argument from the list.

dqcs_return_t dqcs_arb_remove(
    dqcs_handle_t arb,
    ssize_t index
)
dqcs_arb_set_raw()

Replaces the unstructured argument at the specified index with the specified raw object.

dqcs_return_t dqcs_arb_set_raw(
    dqcs_handle_t arb,
    ssize_t index,
    const void *obj,
    size_t obj_size
)
dqcs_arb_set_str()

Replaces the unstructured argument at the specified index with the specified string.

dqcs_return_t dqcs_arb_set_str(
    dqcs_handle_t arb,
    ssize_t index,
    const char *s
)
dqcs_basis_t

Enumeration of Pauli bases.

typedef enum { ... } dqcs_basis_t;

Variants:

DQCS_BASIS_INVALID = 0
Invalid basis. Used as an error return value.
DQCS_BASIS_X = 1
The X basis.

\[ \psi_X = \frac{1}{\sqrt{2}} \begin{bmatrix} 1 & -1 \\ 1 & 1 \end{bmatrix} \]

DQCS_BASIS_Y = 2
The Y basis.

\[ \psi_Y = \frac{1}{\sqrt{2}} \begin{bmatrix} 1 & i \\ i & 1 \end{bmatrix} \]

DQCS_BASIS_Z = 3
The Z basis.

\[ \psi_Z = \begin{bmatrix} 1 & 0 \\ 0 & 1 \end{bmatrix} \]

dqcs_bool_return_t

Return type for functions that normally return a boolean but can also fail.

typedef enum { ... } dqcs_bool_return_t;

Variants:

DQCS_BOOL_FAILURE = -1
The function has failed. More information may be obtained through `dqcsim_explain()`.
DQCS_FALSE = 0
The function did what it was supposed to and returned false.
DQCS_TRUE = 1
The function did what it was supposed to and returned true.

dqcs_cmd_iface_cmp()

Compares the interface ID of an ArbCmd with the given string.

dqcs_bool_return_t dqcs_cmd_iface_cmp(
    dqcs_handle_t cmd,
    const char *iface
)

Returns -1 for failure, 0 for no match, or 1 for a match.

dqcs_cmd_iface_get()

Returns the interface ID of an ArbCmd.

char *dqcs_cmd_iface_get(dqcs_handle_t cmd)

On success, this returns a newly allocated string containing the JSON string. Free it with free() when you're done with it to avoid memory leaks. On failure, this returns NULL.

dqcs_cmd_new()

Creates a new ArbCmd object.

dqcs_handle_t dqcs_cmd_new(
    const char *iface,
    const char *oper
)

Returns the handle of the newly created ArbCmd. The ArbCmd is initialized with the given interface and operation IDs, JSON object {}, and an empty binary argument list. Upon failure, returns 0.

ArbCmd objects support the handle, arb, and cmd interfaces.

dqcs_cmd_oper_cmp()

Compares the operation ID of an ArbCmd with the given string.

dqcs_bool_return_t dqcs_cmd_oper_cmp(
    dqcs_handle_t cmd,
    const char *oper
)

Returns -1 for failure, 0 for no match, or 1 for a match.

dqcs_cmd_oper_get()

Returns the operation ID of an ArbCmd.

char *dqcs_cmd_oper_get(dqcs_handle_t cmd)

On success, this returns a newly allocated string containing the JSON string. Free it with free() when you're done with it to avoid memory leaks. On failure, this returns NULL.

dqcs_cq_len()

Returns the number of ArbCmd objects in the given ArbCmd queue.

ssize_t dqcs_cq_len(dqcs_handle_t cq)

This function returns -1 to indicate failure.

dqcs_cq_new()

Creates a new ArbCmd queue object.

dqcs_handle_t dqcs_cq_new(void)

Returns the handle of the newly created ArbCmd queue. The queue is initially empty. Queues implement a "first-in, first-out" model.

ArbCmd queue objects support the handle, arb, cmd, and cq APIs.

The arb and cmd APIs refer to the ArbCmd at the front of the queue. Use dqcs_cq_next() to remove the front entry, allowing access to the next command.

dqcs_cq_next()

Advances an ArbCmd queue to the next command.

dqcs_return_t dqcs_cq_next(dqcs_handle_t cq)

Use the dqcs_arb_* and dqcs_cmd_* interfaces to read out the command before calling this function.

To iterate over a queue in C, use the following snippit:

for (; dqcs_cq_len(queue) > 0; dqcs_cq_next(queue)) {
    dqcs_cmd_...(queue, ...)
    dqcs_arb_...(queue, ...)
}
dqcs_cq_push()

Pushes an ArbCmd object into the given ArbCmd queue.

dqcs_return_t dqcs_cq_push(
    dqcs_handle_t cq,
    dqcs_handle_t cmd
)

This function returns -1 to indicate failure. The ArbCmd object specified by cmd is moved into the queue. That is, the handle is consumed if and only if the function succeeds.

dqcs_cycle_t

Type for a simulation cycle timestamp.

typedef long long dqcs_cycle_t;

Timestamps count upward from zero. The type is signed to allow usage of -1 for errors, and to allow numerical differences to be represented.

dqcs_error_get()

Returns a pointer to the latest error message.

const char *dqcs_error_get(void)

Call this to get extra information when another function returns a failure code. The returned pointer is temporary and therefore should NOT be free()d. It will become invalid when a new error occurs.

dqcs_error_set()

Sets the latest error message string.

void dqcs_error_set(const char *msg)

This must be called by callback functions when an error occurs within the callback, otherwise the upstream result for dqcs_error_get() will be undefined.

If msg is set to NULL, the error string is cleared instead.

dqcs_gate_controls()

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_expand_control()

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.

dqcs_gate_has_controls()

Returns whether the specified gate has control qubits.

dqcs_bool_return_t dqcs_gate_has_controls(dqcs_handle_t gate)
dqcs_gate_has_matrix()

Returns whether a unitary matrix is associated with this gate.

dqcs_bool_return_t dqcs_gate_has_matrix(dqcs_handle_t gate)
dqcs_gate_has_measures()

Returns whether the specified gate measures any qubits.

dqcs_bool_return_t dqcs_gate_has_measures(dqcs_handle_t gate)
dqcs_gate_has_name()

Returns whether the specified gate has a name.

dqcs_bool_return_t dqcs_gate_has_name(dqcs_handle_t gate)
dqcs_gate_has_targets()

Returns whether the specified gate has target qubits.

dqcs_bool_return_t dqcs_gate_has_targets(dqcs_handle_t gate)
dqcs_gate_matrix()

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_measures()

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_name()

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.

dqcs_gate_new_custom()

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.

dqcs_gate_new_measurement()

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_predef()

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.

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_three()

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_predef_two()

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_prep()

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_unitary()

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_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.

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_targets()

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_type()

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.

dqcs_gate_type_t

Types of DQCsim gates.

typedef enum { ... } dqcs_gate_type_t;

Variants:

DQCS_GATE_TYPE_INVALID = 0
Invalid gate type. Used as an error return value.
DQCS_GATE_TYPE_UNITARY
Unitary gates have one or more target qubits, zero or more control qubits, and a unitary matrix, sized for the number of target qubits.

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.

DQCS_GATE_TYPE_MEASUREMENT
Measurement gates have one or more measured qubits and a 2x2 unitary matrix representing the basis.

The semantics are:

  • the hermetian of the matrix is applied to each individual qubit;
  • each individual qubit is measured in the Z basis;
  • the matrix is applied to each individual qubit;
  • the results of the measurement are propagated upstream.

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.

DQCS_GATE_TYPE_PREP
Prep gates have one or more target qubits and a 2x2 unitary matrix representing the basis.

The semantics are:

  • each qubit is initialized to |0>;
  • the matrix is applied to each individual qubit.

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.

DQCS_GATE_TYPE_CUSTOM
Custom gates perform a user-defined mixed quantum-classical operation, identified by a name. They can have zero or more target, control, and measured qubits, of which only the target and control sets must be mutually exclusive. They also have an optional matrix of arbitrary size.

The semantics are:

  • if the name is not recognized, an error is reported;
  • a user-defined operation is performed based on the name, qubits, matrix, and data arguments;
  • exactly one measurement result is reported upstream for exactly the qubits in the measures set.

dqcs_gm_add_custom()

Adds a fully customizable gate mapping to the given gate map.

dqcs_return_t dqcs_gm_add_custom(
    dqcs_handle_t gm,
    void (*key_free)(void *key_data),
    void *key_data,
    dqcs_bool_return_t (*detector)(
        const void *user_data,
        dqcs_handle_t gate,
        dqcs_handle_t *qubits,
        dqcs_handle_t *param_data
    ),
    void (*detector_user_free)(void *user_data),
    void *detector_user_data,
    dqcs_handle_t (*constructor)(
        const void *user_data,
        dqcs_handle_t qubits,
        dqcs_handle_t param_data
    ),
    void (*constructor_user_free)(void *user_data),
    void *constructor_user_data
)

Note that this is the only type of mapping that can handle custom/named gates.

detector is the detector function pointer. It is optional; if null, this mapping only supports construction. detector_user_free is an optional callback function used to free detector_user_data when the gate map is destroyed, when this function fails, or when detector was null. detector_user_data is a user-specified value that is passed to the detector callback function. It is not used by DQCsim. constructor is the constructor function pointer. It is optional; if null, this mapping only supports detection. constructor_user_free is an optional callback function used to free constructor_user_data when the gate map is destroyed, when this function fails, or when constructor was null. constructor_user_data is a user-specified value that is passed to the constructor callback function. It is not used by DQCsim.

If both constructor and detector are null for some reason, the function is no-op (besides possibly calling the *_free() callbacks.

The detector callback receives the complete gate passed to the gate map for it to match as it pleases. If the gate matches, the detector function must return DQCS_TRUE. It may assign qubits to a qbset object representing the qubit arguments (substituted with an empty set if it doesn't), and may assign param_data to an arb handle with the parameterization data (if it doesn't, the data from the gate is used; if this was modified by the callback, the modified data is used). If the gate doesn't match, it must return DQCS_FALSE. If an error occurs, it must call dqcs_error_set() with the error message and return DQCS_BOOL_FAILURE.

The constructor callback performs the reverse operation. It receives an ArbData handle containing the parameterization data and a qubit set, and must construct a gate based on this information. If construction succeeds, the constructor function must return the gate handle. If an error occurs, it must call dqcs_error_set() with the error message and return 0.

It is up to the user how to do the matching and constructing, but the converter functions must always return the same value for the same input. In other words, they must be pure functions. Otherwise, the caching behavior of the GateMap will make the results inconsistent.

dqcs_gm_add_custom_unitary()

Adds a custom unitary gate mapping to the given gate map.

dqcs_return_t dqcs_gm_add_custom_unitary(
    dqcs_handle_t gm,
    void (*key_free)(void *key_data),
    void *key_data,
    dqcs_bool_return_t (*detector)(
        const void *user_data,
        dqcs_handle_t matrix,
        size_t num_controls,
        dqcs_handle_t *param_data
    ),
    void (*detector_user_free)(void *user_data),
    void *detector_user_data,
    dqcs_handle_t (*constructor)(
        const void *user_data,
        dqcs_handle_t *param_data,
        intptr_t *num_controls
    ),
    void (*constructor_user_free)(void *user_data),
    void *constructor_user_data
)

gm must be a handle to a gate map object (dqcs_gm_new()). key_free is an optional callback function used to free key_data when the gate map is destroyed, or when this function fails. key_data is the user-specified value used to identify this mapping. detector is the detector function pointer. It is optional; if null, this mapping only supports construction. detector_user_free is an optional callback function used to free detector_user_data when the gate map is destroyed, when this function fails, or when detector was null. detector_user_data is a user-specified value that is passed to the detector callback function. It is not used by DQCsim. constructor is the constructor function pointer. It is optional; if null, this mapping only supports detection. constructor_user_free is an optional callback function used to free constructor_user_data when the gate map is destroyed, when this function fails, or when constructor was null. constructor_user_data is a user-specified value that is passed to the constructor callback function. It is not used by DQCsim.

If both constructor and detector are null for some reason, the function is no-op (besides possibly calling the *_free() callbacks.

The detector callback receives a matrix and control qubit information for the user to match. The matrix is passed through the matrix handle. num_controls is passed the number of explicit control qubits that exist besides the matrix (that is, if nonzero, the matrix is actually only the non-controlled submatrix of the controlled gate). param_data is given an ArbData handle initialized with the ArbData attached to the gate. If the gate matches, the detector function must return DQCS_TRUE. In this case, it can mutate the param_data to add the detected gate parameters. If it doesn't match, it must return DQCS_FALSE. If an error occurs, it must call dqcs_error_set() with the error message and return DQCS_BOOL_FAILURE.

The constructor callback performs the reverse operation. It receives an ArbData handle containing the parameterization data, and must construct the matrix, return the bound on the number of control qubits, and must return the ArbData associated with the gate by mutating the param_data handle. num_controls will point to a variable initialized to -1 representing a constraint on the number of control qubits. This works as follows: if negative, any number of qubits is allowed; if zero or positive, only that number is allowed. If construction succeeds, the constructor function must return a handle to the constructed matrix. If it fails, it must call dqcs_error_set() with an error message and return 0.

It is up to the user how to do the matching and constructing, but the converter functions must always return the same value for the same input. In other words, they must be pure functions. Otherwise, the caching behavior of the GateMap will make the results inconsistent.

dqcs_gm_add_fixed_unitary()

Adds a unitary gate mapping for the given gate matrix to the given gate map.

dqcs_return_t dqcs_gm_add_fixed_unitary(
    dqcs_handle_t gm,
    void (*key_free)(void *key_data),
    void *key_data,
    dqcs_handle_t matrix,
    intptr_t num_controls,
    double epsilon,
    bool ignore_gphase
)

gm must be a handle to a gate map object (dqcs_gm_new()). key_free is an optional callback function used to free key_data when the gate map is destroyed, or when this function fails. key_data is the user-specified value used to identify this mapping. matrix must be passed a handle to the matrix to detect. It is consumed by this function. num_controls specifies the number of control qubits associated with this gate type. If negative, the gate can have any number of control qubits. If zero or positive, the number of control qubits must be as specified. epsilon specifies the maximum element-wise root-mean-square error between the incoming matrix and the to be detected matrix that results in a positive match. ignore_phase specifies whether the aforementioned check should ignore global phase or not when there are no explicit control qubits.

The parameterization ArbData object returned by detection and consumed by construction is mapped one-to-one to the user data of the gate in the DQCsim-protocol.

dqcs_gm_add_measure()

Adds a measurement gate mapping to the given gate map.

dqcs_return_t dqcs_gm_add_measure(
    dqcs_handle_t gm,
    void (*key_free)(void *user_data),
    void *key_data,
    intptr_t num_measures,
    dqcs_handle_t basis,
    double epsilon
)

gm must be a handle to a gate map object (dqcs_gm_new()). key_free is an optional callback function used to free key_data when the gate map is destroyed, or when this function fails. key_data is the user-specified value used to identify this mapping. num_measures specifies the number of measured qubits for this gate type. If negative, the gate can have any number of measured qubits. If zero or positive, the number of measured qubits must be as specified. basis optionally specifies a handle to a 2x2 matrix specifying the measurement basis to be detected. If not specified, the Z basis is used. The matrix is deleted by the call iff the function succeeds. epsilon specifies the maximum RMS deviation between the specified basis (if any) and the incoming basis.

The parameterization ArbData object returned by detection and consumed by construction is mapped one-to-one to the user data of the gate in the DQCsim-protocol.

dqcs_gm_add_predef_unitary()

Adds a unitary gate mapping for the given DQCsim-defined gate to the given gate map.

dqcs_return_t dqcs_gm_add_predef_unitary(
    dqcs_handle_t gm,
    void (*key_free)(void *user_data),
    void *key_data,
    dqcs_predefined_gate_t gate,
    intptr_t num_controls,
    double epsilon,
    bool ignore_gphase
)

gm must be a handle to a gate map object (dqcs_gm_new()). key_free is an optional callback function used to free key_data when the gate map is destroyed, or when this function fails. key_data is the user-specified value used to identify this mapping. gate defines which predefined gate to use. Some of the predefined gates are parameterized. num_controls specifies the number of control qubits associated with this gate type. If negative, the gate can have any number of control qubits. If zero or positive, the number of control qubits must be as specified. epsilon specifies the maximum element-wise root-mean-square error between the incoming matrix and the to be detected matrix that results in a positive match. ignore_phase specifies whether the aforementioned check should ignore global phase or not when there are no explicit control qubits.

For most gate types, the parameterization ArbData object returned by detection and consumed by construction is mapped one-to-one to the user data of the gate in the DQCsim-protocol. Some of the detectors however detect parameterized gate matrices. These detectors prefix a fixed number of binary string arguments to the ArbData upon detection, and pop these when constructing. The specs for this can be found in the docs for dqcs_predefined_gate_t.

dqcs_gm_add_prep()

Adds a prep gate mapping to the given gate map.

dqcs_return_t dqcs_gm_add_prep(
    dqcs_handle_t gm,
    void (*key_free)(void *user_data),
    void *key_data,
    intptr_t num_targets,
    dqcs_handle_t basis,
    double epsilon
)

gm must be a handle to a gate map object (dqcs_gm_new()). key_free is an optional callback function used to free key_data when the gate map is destroyed, or when this function fails. key_data is the user-specified value used to identify this mapping. num_targets specifies the number of target qubits for this gate type. If negative, the gate can have any number of targets. If zero or positive, the number of target qubits must be as specified. basis optionally specifies a handle to a 2x2 matrix specifying the prep basis. If not specified, the Z basis is used. The matrix is deleted by the call iff the function succeeds. epsilon specifies the maximum RMS deviation between the specified basis (if any) and the incoming basis.

The parameterization ArbData object returned by detection and consumed by construction is mapped one-to-one to the user data of the gate in the DQCsim-protocol.

dqcs_gm_construct()

Uses a gate map object to construct a multi-qubit DQCsim gate from the plugin's representation.

dqcs_handle_t dqcs_gm_construct(
    dqcs_handle_t gm,
    const void *key_data,
    dqcs_handle_t qubits,
    dqcs_handle_t param_data
)

gm must be a handle to a gate map object (dqcs_mm_new()). gate must be a handle to a gate. The handle is borrowed; it is not mutated or deleted. key_data specifies the gate mapping key for the constructor to use. Note that the pointer must match exactly to what was specified when the mapping(s) was/were added. qubits specifies the qubits arguments for the constructed gate. It is up to the constructor function to determine how to interpret these. The parameter is optional; passing 0 is equivalent to passing an empty qubit set. The handle is deleted if the function succeeds. param_data specifies the ArbData object used to parameterize the gate. It is optional; if 0, an empty ArbData is automatically constructed by DQCsim. The handle is deleted if the function succeeds.

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_gm_construct_one()

Uses a gate map object to construct a one-qubit DQCsim gate from the plugin's representation.

dqcs_handle_t dqcs_gm_construct_one(
    dqcs_handle_t gm,
    const void *key_data,
    dqcs_qubit_t qa,
    dqcs_handle_t param_data
)

This function is simply a shorthand for dqcs_gm_construct() with one qubit in the qubits set, to make constructing one-qubit gates more ergonomic. Refer to its documentation for more information.

dqcs_gm_construct_three()

Uses a gate map object to construct a three-qubit DQCsim gate from the plugin's representation.

dqcs_handle_t dqcs_gm_construct_three(
    dqcs_handle_t gm,
    const void *key_data,
    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_gm_construct() with three qubits in the qubits set, to make constructing three-qubit gates more ergonomic. Refer to its documentation for more information.

dqcs_gm_construct_two()

Uses a gate map object to construct a two-qubit DQCsim gate from the plugin's representation.

dqcs_handle_t dqcs_gm_construct_two(
    dqcs_handle_t gm,
    const void *key_data,
    dqcs_qubit_t qa,
    dqcs_qubit_t qb,
    dqcs_handle_t param_data
)

This function is simply a shorthand for dqcs_gm_construct() with two qubits in the qubits set, to make constructing two-qubit gates more ergonomic. Refer to its documentation for more information.

dqcs_gm_detect()

Uses a gate map object to convert an incoming DQCsim gate to the plugin's representation.

dqcs_bool_return_t dqcs_gm_detect(
    dqcs_handle_t gm,
    dqcs_handle_t gate,
    const void **key_data,
    dqcs_handle_t *qubits,
    dqcs_handle_t *param_data
)

gm must be a handle to a gate map object (dqcs_mm_new()). gate must be a handle to a gate. The handle is borrowed; it is not mutated or deleted. key_data serves as an optional return value; if non-NULL and a match is found, the key_data specified when the respective detector was added is returned here as a const void *. If no match is found, *key_data is not assigned. qubits serves as an optional return value; if non-NULL and a match is found, it is set to a handle to a new QubitSet object representing the gate's qubits. Ownership of this handle is passed to the user, so it is up to the user to eventually delete it. If no match is found, *qubits is set to 0. param_data serves as an optional return value; if non-NULL and a match is found, it is set to a handle to a new ArbData object representing the gate's parameters. Ownership of this handle is passed to the user, so it is up to the user to eventually delete it. If no match is found, *param_data is set to 0.

This function returns DQCS_TRUE if a match was found, DQCS_FALSE if no match was found, or DQCS_BOOL_FAILURE if an error occurs.

dqcs_gm_new()

Constructs a new gate map.

dqcs_handle_t dqcs_gm_new(
    bool strip_qubit_refs,
    bool strip_data,
    bool (*key_cmp)(
        const void,
        const void
    ),
    uint64_t (*key_hash)(const void)
)

Returns a handle to a gate map with no mappings attached to it yet. Use dqcs_gm_add_*() to do that. The mappings are queried in the order in which they are added, so be sure to add more specific gates first. Once added, use dqcs_gm_detect() to detect incoming DQCsim gates, and dqcs_gm_construct*() to (re)construct gates for transmission.

Gate maps objects retain a cache to speed up detection of similar DQCsim gates: if a gate is received for the second time, the cache will hit, avoiding recomputation of the detector functions. What constitutes "similar gates" is defined by the two booleans passed to this function. If strip_qubit_refs is set, all qubit references associated with the gate will be invalidated (i.e., set to 0), such that for instance an X gate applied to qubit 1 will be considered equal to an X gate applied to qubit 2. If strip_data is set, the ArbData associated with the incoming gate is removed.

Gates are identified through user-defined void* keys. To do the above, however, DQCsim needs to know the following things:

  • how to delete an owned copy of a key if your semantics are that DQCsim owns it,
  • how to compare two keys (equality);
  • how to hash a key.

The deletion function is passed when the key is passed. If the keys are objects of different classes, this allows different constructors to be passed here. There can only be a single comparison and hash function for each gate map, though. They are passed here.

key_cmp represents this comparison function. It takes two void* to keys and must returns whether they are equal or not. If not specified, the default is to compare the pointers themselves, instead of the values they refer to. key_cmp must be a pure function, i.e., depend only on its input values.

key_hash represents the hashing function. It takes a void* key and returns a 64-bit hash representative of the key. For any pair of keys for which key_cmp returns true, the hashes must be equal. The default behavior depends on whether key_cmp is defined: if it is, all keys will have the same hash; if it isn't, the pointer is itself hashed. key_hash must be a pure function, i.e., depend only on its input values.

It is recommended to first preprocess incoming gates with dqcs_gate_reduce_control(). In this case, controlled unitary gate matrices will be reduced to their non-controlled submatrix, such that the unitary gate detectors will operate on said submatrix. The predefined unitary gate detectors are more-or-less based on this assumption (as there are no predefined controlled matrices).

Alternatively, you can preprocess with dqcs_gate_expand_control(). In this case, you can use dqcs_gm_add_fixed_unitary() to detect the full matrix in all cases, by specifying the CNOT matrix instead of an X matrix with one control qubit.

If you don't preprocess, the upstream plugin determines the representation. That is, it may send a CNOT as a two-qubit gate with a CNOT matrix or as a controlled X gate with a single target and single control qubit. The gate map will then detect these as two different kinds of gates.

dqcs_handle_delete()

Destroys the object associated with a handle.

dqcs_return_t dqcs_handle_delete(dqcs_handle_t handle)

Returns 0 when successful, -1 otherwise.

dqcs_handle_delete_all()

Deletes all handles for the current thread.

dqcs_return_t dqcs_handle_delete_all(void)

This can be used to clean stuff up at the end of main() or before an abort() of some kind. If you don't clean up properly, you might get undefined behavior or errors when DQCsim tries to do it for you.

dqcs_handle_dump()

Returns a debug dump of the object associated with the given handle.

char *dqcs_handle_dump(dqcs_handle_t handle)

On success, this returns a newly allocated string containing the description. Free it with free() when you're done with it to avoid memory leaks. On failure (i.e., the handle is invalid) this returns NULL.

dqcs_handle_leak_check()

Succeeds only if there are no live handles in the current thread.

dqcs_return_t dqcs_handle_leak_check(void)

This is intended for testing and for finding handle leaks. The error message returned when handles remain contains dumps of the first 10 remaining handles.

dqcs_handle_t

Type for a handle.

typedef unsigned long long dqcs_handle_t;

Handles are like pointers into DQCsim's internal structures: all API calls use these to refer to objects. Besides the object, they contain type information. This type can be retrieved using dqcs_handle_type().

Handles are always positive integers, counting upwards from 1 upon allocation, and they are not reused even after being deleted. Thus, every subsequent object allocation returns a handle one greater than the previous. Note however that DQCsim may allocate objects as well without the user specifically requesting this, so external code should generally not rely on this behavior unless otherwise noted. The value zero is reserved for invalid references or error propagation.

Note that the scope for handles is thread-local. That is, data referenced by a handle cannot be shared or moved between threads.

The value zero is reserved for invalid references or error propagation.

dqcs_handle_type()

Returns the type of object associated with the given handle.

dqcs_handle_type_t dqcs_handle_type(dqcs_handle_t handle)
dqcs_handle_type_t

Enumeration of types that can be associated with a handle.

typedef enum { ... } dqcs_handle_type_t;

Variants:

DQCS_HTYPE_INVALID = 0
Indicates that the given handle is invalid.

This indicates one of the following:

  • The handle value is invalid (zero or negative).
  • The handle has not been used yet.
  • The object associated with the handle was deleted.
DQCS_HTYPE_ARB_DATA = 100
Indicates that the given handle belongs to an `ArbData` object.

This means that the handle supports the handle and arb interfaces.

DQCS_HTYPE_ARB_CMD = 101
Indicates that the given handle belongs to an `ArbCmd` object.

This means that the handle supports the handle, arb, and cmd interfaces.

DQCS_HTYPE_ARB_CMD_QUEUE = 102
Indicates that the given handle belongs to a queue of `ArbCmd` object.

This means that the handle supports the handle, arb, cmd, and cq interfaces.

DQCS_HTYPE_QUBIT_SET = 103
Indicates that the given handle belongs to a set of qubit references.

This means that the handle supports the handle and qbset interfaces.

DQCS_HTYPE_GATE = 104
Indicates that the given handle belongs to a quantum gate description.

This means that the handle supports the handle, gate, and arb interfaces.

DQCS_HTYPE_MEAS = 105
Indicates that the given handle belongs to a qubit measurement result.

This means that the handle supports the handle, meas, and arb interfaces. It can also be used in place of a qubit measurement result set by functions that consume the object.

DQCS_HTYPE_MEAS_SET = 106
Indicates that the given handle belongs to a set of qubit measurement results.

This means that the handle supports the handle and mset interfaces.

DQCS_HTYPE_MATRIX = 107
Indicates that the given handle belongs to a matrix.

This means that the handle supports the handle and mat interfaces.

DQCS_HTYPE_GATE_MAP = 108
Indicates that the given handle belongs to a gate map.

This means that the handle supports the handle and gm interfaces.

DQCS_HTYPE_FRONT_PROCESS_CONFIG = 200
Indicates that the given handle belongs to a frontend plugin process configuration object.

This means that the handle supports the handle, pcfg, and xcfg interfaces.

DQCS_HTYPE_OPER_PROCESS_CONFIG = 201
Indicates that the given handle belongs to an operator plugin process configuration object.

This means that the handle supports the handle, pcfg, and xcfg interfaces.

DQCS_HTYPE_BACK_PROCESS_CONFIG = 203
Indicates that the given handle belongs to a backend plugin process configuration object.

This means that the handle supports the handle, pcfg, and xcfg interfaces.

DQCS_HTYPE_FRONT_THREAD_CONFIG = 204
Indicates that the given handle belongs to a frontend plugin thread configuration object.

This means that the handle supports the handle, tcfg, and xcfg interfaces.

DQCS_HTYPE_OPER_THREAD_CONFIG = 205
Indicates that the given handle belongs to an operator plugin thread configuration object.

This means that the handle supports the handle, tcfg, and xcfg interfaces.

DQCS_HTYPE_BACK_THREAD_CONFIG = 206
Indicates that the given handle belongs to a backend plugin thread configuration object.

This means that the handle supports the handle, tcfg, and xcfg interfaces.

DQCS_HTYPE_SIM_CONFIG = 207
Indicates that the given handle belongs to a simulator configuration object.

This means that the handle supports the handle and scfg interfaces.

DQCS_HTYPE_SIM = 208
Indicates that the given handle belongs to a simulator instance.

This means that the handle supports the handle and sim interfaces.

DQCS_HTYPE_FRONT_DEF = 300
Indicates that the given handle belongs to a frontend plugin definition object.

This means that the handle supports the handle and pdef interfaces.

DQCS_HTYPE_OPER_DEF = 301
Indicates that the given handle belongs to an operator plugin definition object.

This means that the handle supports the handle and pdef interfaces.

DQCS_HTYPE_BACK_DEF = 302
Indicates that the given handle belongs to a backend plugin definition object.

This means that the handle supports the handle and pdef interfaces.

DQCS_HTYPE_PLUGIN_JOIN = 303
Indicates that the given handle belongs to a plugin thread join handle.

This means that the handle supports the handle and pjoin interfaces.

dqcs_log_debug()

Convenience macro for calling dqcs_log_format() with debug loglevel and automatically determined function name, filename, and line number.

#define dqcs_log_debug(fmt, ...)                \
  dqcs_log_format(                              \
    _DQCSIM_LOGLEVEL_PREFIX_ DQCS_LOG_DEBUG,    \
    _DQCSIM_LANGUAGE_,                          \
    __FILE__,                                   \
    __LINE__,                                   \
    fmt,                                        \
    ##__VA_ARGS__                               \
  )
dqcs_log_error()

Convenience macro for calling dqcs_log_format() with error loglevel and automatically determined function name, filename, and line number.

#define dqcs_log_error(fmt, ...)                \
  dqcs_log_format(                              \
    _DQCSIM_LOGLEVEL_PREFIX_ DQCS_LOG_ERROR,    \
    _DQCSIM_LANGUAGE_,                          \
    __FILE__,                                   \
    __LINE__,                                   \
    fmt,                                        \
    ##__VA_ARGS__                               \
  )
dqcs_log_fatal()

Convenience macro for calling dqcs_log_format() with fatal loglevel and automatically determined function name, filename, and line number.

#define dqcs_log_fatal(fmt, ...)                \
  dqcs_log_format(                              \
    _DQCSIM_LOGLEVEL_PREFIX_ DQCS_LOG_FATAL,    \
    _DQCSIM_LANGUAGE_,                          \
    __FILE__,                                   \
    __LINE__,                                   \
    fmt,                                        \
    ##__VA_ARGS__                               \
  )
dqcs_log_format()

Sends a log message using the current logger using printf-like formatting.

static void dqcs_log_format(
    dqcs_loglevel_t level,
    const char *module,
    const char *file,
    uint32_t line,
    const char *fmt,
    ...
)

This function is identical to dqcs_log_raw(), except instead of a single string it takes a printf-like format string and varargs to compose the message.

dqcs_log_info()

Convenience macro for calling dqcs_log_format() with info loglevel and automatically determined function name, filename, and line number.

#define dqcs_log_info(fmt, ...)                 \
  dqcs_log_format(                              \
    _DQCSIM_LOGLEVEL_PREFIX_ DQCS_LOG_INFO,     \
    _DQCSIM_LANGUAGE_,                          \
    __FILE__,                                   \
    __LINE__,                                   \
    fmt,                                        \
    ##__VA_ARGS__                               \
  )
dqcs_log_note()

Convenience macro for calling dqcs_log_format() with note loglevel and automatically determined function name, filename, and line number.

#define dqcs_log_note(fmt, ...)                 \
  dqcs_log_format(                              \
    _DQCSIM_LOGLEVEL_PREFIX_ DQCS_LOG_NOTE,     \
    _DQCSIM_LANGUAGE_,                          \
    __FILE__,                                   \
    __LINE__,                                   \
    fmt,                                        \
    ##__VA_ARGS__                               \
  )
dqcs_log_raw()

Primitive API for sending a log message using the current logger.

dqcs_return_t dqcs_log_raw(
    dqcs_loglevel_t level,
    const char *module,
    const char *file,
    uint32_t line_nr,
    const char *message
)

Returns DQCS_SUCCESS if logging was successful, or DQCS_FAILURE if no logger is available in the current thread or one of the arguments could not be converted. Loggers are available in the simulation host thread and in threads running plugins.

Formatting and fallback to stderr

As an alternative to this function, you can also use dqcs_log_format(). This function differs from dqcs_log_raw() in two ways:

  • Instead of the message string, a printf-style format string and associated varargs are passed to construct the message.
  • When logging fails, this function falls back to writing to stderr instead of returning the errors.

Macros

From C and C++, these functions are normally not called directly. Instead, the following macros are used:

dqcs_log_trace("trace message!");
dqcs_log_debug("debug message!");
dqcs_log_info("info message!");
dqcs_log_note("notice!");
dqcs_log_warn("warning!");
dqcs_log_error("error!");
dqcs_log_fatal("fatal error!");

These macros automatically set file to the C source filename and line to the line number. module is hardcoded to "C" or "CPP" depending on source file language. They use dqcs_log_format(), so they also support printf-style formatting. For instance:

dqcs_note("answer to %s: %d", "ultimate question", 42);
dqcs_log_trace()

Convenience macro for calling dqcs_log_format() with trace loglevel and automatically determined function name, filename, and line number.

#define dqcs_log_trace(fmt, ...)                \
  dqcs_log_format(                              \
    _DQCSIM_LOGLEVEL_PREFIX_ DQCS_LOG_TRACE,    \
    _DQCSIM_LANGUAGE_,                          \
    __FILE__,                                   \
    __LINE__,                                   \
    fmt,                                        \
    ##__VA_ARGS__                               \
  )
dqcs_log_warn()

Convenience macro for calling dqcs_log_format() with warn loglevel and automatically determined function name, filename, and line number.

#define dqcs_log_warn(fmt, ...)                 \
  dqcs_log_format(                              \
    _DQCSIM_LOGLEVEL_PREFIX_ DQCS_LOG_WARN,     \
    _DQCSIM_LANGUAGE_,                          \
    __FILE__,                                   \
    __LINE__,                                   \
    fmt,                                        \
    ##__VA_ARGS__                               \
  )
dqcs_loglevel_t

Enumeration of loglevels and logging modes.

typedef enum { ... } dqcs_loglevel_t;

Variants:

DQCS_LOG_INVALID = -1
Invalid loglevel. Used to indicate failure of an API that returns a loglevel.
DQCS_LOG_OFF = 0
Turns logging off.
DQCS_LOG_FATAL = 1
This loglevel is to be used for reporting a fatal error, resulting from the owner of the logger getting into an illegal state from which it cannot recover. Such problems are also reported to the API caller via Result::Err if applicable.
DQCS_LOG_ERROR = 2
This loglevel is to be used for reporting or propagating a non-fatal error caused by the API caller doing something wrong. Such problems are also reported to the API caller via Result::Err if applicable.
DQCS_LOG_WARN = 3
This loglevel is to be used for reporting that a called API/function is telling us we did something wrong (that we weren't expecting), but we can recover. For instance, for a failed connection attempt to something that really should not be failing, we can still retry (and eventually report critical or error if a retry counter overflows). Since we're still trying to rectify things at this point, such problems are NOT reported to the API/function caller via Result::Err.
DQCS_LOG_NOTE = 4
This loglevel is to be used for reporting information specifically requested by the user/API caller, such as the result of an API function requested through the command line, or an explicitly captured stdout/stderr stream.
DQCS_LOG_INFO = 5
This loglevel is to be used for reporting information NOT specifically requested by the user/API caller, such as a plugin starting up or shutting down.
DQCS_LOG_DEBUG = 6
This loglevel is to be used for reporting debugging information useful for debugging the user of the API provided by the logged instance.
DQCS_LOG_TRACE = 7
This loglevel is to be used for reporting debugging information useful for debugging the internals of the logged instance. Such messages would normally only be generated by debug builds, to prevent them from impacting performance under normal circumstances.
DQCS_LOG_PASS = 8
This is intended to be used when configuring the stdout/stderr capture mode for a plugin process. Selecting it will prevent the stream from being captured; it will just be the same stream as DQCsim's own stdout/stderr. When used as the loglevel for a message, the message itself is sent to stderr instead of passing into DQCsim's log system. Using this for loglevel filters leads to undefined behavior.

dqcs_mat_add_controls()

Constructs a controlled matrix from the given matrix.

dqcs_handle_t dqcs_mat_add_controls(
    dqcs_handle_t mat,
    size_t number_of_controls
)

mat specifies the matrix to use as the non-controlled submatrix. This is a borrowed handle. number_of_controls specifies the number of control qubits to add. This function returns a new matrix handle with the constructed matrix, or 0 if it fails.

dqcs_mat_approx_eq()

Approximately compares two matrices.

dqcs_bool_return_t dqcs_mat_approx_eq(
    dqcs_handle_t a,
    dqcs_handle_t b,
    double epsilon,
    bool ignore_gphase
)

a and b are borrowed matrix handles. epsilon specifies the maximum element-wise root-mean-square error between the matrices that results in a positive match. ignore_gphase specifies whether the check should ignore global phase.

If ignore_gphase is set, this checks that the following holds for some x:

\[ A \cdot e^{ix} \approx B \]

This function returns DQCS_TRUE if the matrices match according to the aforementioned criteria, or DQCS_FALSE if not. DQCS_BOOL_ERROR is used when either handle is invalid or not a matrix. If the matrices differ in dimensionality, DQCS_FALSE is used.

dqcs_mat_approx_unitary()

Returns whether the matrix is approximately unitary.

dqcs_bool_return_t dqcs_mat_approx_unitary(
    dqcs_handle_t matrix,
    double epsilon
)

matrix is a borrowed handle to the matrix to check. epsilon specifies the maximum element-wise root-mean-square error between the product of the matrix and its hermetian compared to the identity matrix.

This function returns DQCS_TRUE if the matrix is approximately unitary, or DQCS_FALSE if not. DQCS_BOOL_ERROR is used when either handle is invalid or not a matrix.

dqcs_mat_basis()

Constructs a matrix with the eigenvectors of one of the Pauli matrices as column vectors.

dqcs_handle_t dqcs_mat_basis(dqcs_basis_t basis)

This can be used for constructing measurement or prep gates with the given basis. Returns a new handle to the constructed matrix or returns 0 if an error occurs.

dqcs_mat_basis_approx_eq()

Approximately compares two basis matrices.

dqcs_bool_return_t dqcs_mat_basis_approx_eq(
    dqcs_handle_t a,
    dqcs_handle_t b,
    double epsilon
)

a and b are borrowed matrix handles. epsilon specifies the maximum element-wise root-mean-square error between the matrices that results in a positive match.

This checks that the following holds for some x and y:

\[ A \cdot \begin{bmatrix} e^{ix} & 0 \\ 0 & e^{iy} \end{bmatrix} \approx B \]

This function returns DQCS_TRUE if the matrices match according to the aforementioned criteria, or DQCS_FALSE if not. DQCS_BOOL_ERROR is used when either handle is invalid or not a matrix. If either matrix is not 2x2, DQCS_FALSE is used.

dqcs_mat_dimension()

Returns the dimension (number of rows == number of columns) of the given matrix.

ssize_t dqcs_mat_dimension(dqcs_handle_t mat)

This function returns -1 when an error occurs.

dqcs_mat_get()

Returns a copy of the contained matrix as a C array.

double *dqcs_mat_get(dqcs_handle_t mat)

If this function succeeds, the matrix is returned in row-major form, using pairs of doubles for the real vs. imaginary component of each entry. The size will be 4**num_qubits complex numbers = 2*4**num_qubits doubles = 16*4**num_qubits bytes. A newly allocated matrix is returned; free it with free() when you're done with it to avoid memory leaks. On failure, this function returns NULL.

dqcs_mat_is_predef()

Returns whether this matrix is of the given predefined form and, if it is, any parameters needed to describe it.

dqcs_bool_return_t dqcs_mat_is_predef(
    dqcs_handle_t mat,
    dqcs_predefined_gate_t gate_type,
    dqcs_handle_t *param_data,
    double epsilon,
    bool ignore_gphase
)

mat is a borrowed handle to the matrix to check. gate_type specifies which kind of gate should be detected. param_data, if non-null, receives a new ArbData handle with parameterization data, or an empty ArbData if the gate is not parameterized; the caller must delete this object when it is done with it. This function always writes the 0 handle to this return parameter if it fails. The ArbData representation can be found in the documentation for dqcs_predefined_gate_t.

epsilon specifies the maximum element-wise root-mean-square error between the matrices that results in a positive match. ignore_gphase specifies whether the check should ignore global phase.

This function returns DQCS_TRUE if the matrices match according to the aforementioned criteria, or DQCS_FALSE if not. DQCS_BOOL_ERROR is used when either handle is invalid or not a matrix. If the matrices differ in dimensionality, DQCS_FALSE is used.

dqcs_mat_len()

Returns the number of complex entries in the given matrix.

ssize_t dqcs_mat_len(dqcs_handle_t mat)

This function returns -1 when an error occurs.

dqcs_mat_new()

Constructs a new gate matrix.

dqcs_handle_t dqcs_mat_new(
    size_t num_qubits,
    const double *matrix
)

num_qubits must be set to the number of qubits mutated by this matrix. It must be greater than or equal to zero. matrix must point to an appropriately sized array of doubles. The matrix is specified in row-major form, using pairs of doubles for the real vs. imaginary component of each entry. The size must be 4**num_qubits complex numbers = 2*4**num_qubits doubles = 16*4**num_qubits bytes, representing a 2**num_qubits by 2**num_qubits matrix. This function returns the constructed matrix handle, or 0 if an error occurs.

While not enforced at this level, the matrix is normally unitary, or approximately so within some floating-point error margin.

This function returns the handle to the matrix, or 0 to indicate failure.

dqcs_mat_num_qubits()

Returns the number of qubits targeted by the given matrix.

ssize_t dqcs_mat_num_qubits(dqcs_handle_t mat)

This function returns -1 when an error occurs.

dqcs_mat_predef()

Constructs a new gate matrix for one of DQCsim's predefined gates.

dqcs_handle_t dqcs_mat_predef(
    dqcs_predefined_gate_t gate_type,
    dqcs_handle_t param_data
)

gate_type specifies which kind of gate should be constructed.

param_data takes an optional ArbData object used to parameterize the matrix if necessary. If not specified, an empty object is used. The ArbData representation for each gate can be found in the docs for dqcs_predefined_gate_t. If nothing is specified, no ArbData is used.

This function returns the handle to the matrix, or 0 to indicate failure. The parameterization data (if specified) is consumed/deleted by this function if and only if it succeeds.

dqcs_mat_strip_control()

Splits a controlled matrix into its non-controlled submatrix and the indices of the control qubits.

dqcs_handle_t dqcs_mat_strip_control(
    dqcs_handle_t mat,
    double epsilon,
    bool ignore_global_phase,
    ssize_t **control_indices
)

mat specifies the matrix to modify. This is a borrowed handle. epsilon specifies the maximum magitude of the difference between the column vectors of the input matrix and the identity matrix (after dephasing if ignore_gphase is set) for the column vector to be considered to not affect the respective entry in the quantum state vector. Note that if this is greater than zero, the resulting gate may not be exactly equivalent. If ignore_global_phase is set, any global phase in the matrix is ignored, but note that if control qubits are stripped the "global" phase of the resulting submatrix is always significant. control_indices is a return argument through which DQCsim will pass the indices of the qubits that were removed in the process of constructing the submatrix. This is represented as an array of indices terminated by a -1 entry. The returned matrix must be freed using free() when you are done with it to avoid memory leaks. This function returns a new matrix handle with the submatrix, or 0 if it fails. In this case, control_indices is not mutated.

This function assumes that the incoming matrix is unitary (within epsilon) without verifying that this is the case. The results may thus be invalid if it was not.

dqcs_meas_new()

Constructs a new measurement object.

dqcs_handle_t dqcs_meas_new(
    dqcs_qubit_t qubit,
    dqcs_measurement_t value
)

qubit must be set to the qubit that was measured, value must be set to its value. The return value is the handle to the measurement object, or 0 if something went wrong.

Note that measurement objects implement the arb interface, so additional data can be attached to the object.

dqcs_meas_qubit_get()

Returns the qubit reference associated with a measurement object.

dqcs_qubit_t dqcs_meas_qubit_get(dqcs_handle_t meas)
dqcs_meas_qubit_set()

Sets the qubit reference associated with a measurement object.

dqcs_return_t dqcs_meas_qubit_set(
    dqcs_handle_t meas,
    dqcs_qubit_t qubit
)
dqcs_meas_value_get()

Returns the measurement value associated with a measurement object.

dqcs_measurement_t dqcs_meas_value_get(dqcs_handle_t meas)
dqcs_meas_value_set()

Sets the measurement value associated with a measurement object.

dqcs_return_t dqcs_meas_value_set(
    dqcs_handle_t meas,
    dqcs_measurement_t value
)
dqcs_measurement_t

Qubit measurement value.

typedef enum { ... } dqcs_measurement_t;

Variants:

DQCS_MEAS_INVALID = -1
Error value used to indicate that something went wrong.
DQCS_MEAS_ZERO = 0
Indicates that the qubit was measured to be zero.
DQCS_MEAS_ONE = 1
Indicates that the qubit was measured to be one.
DQCS_MEAS_UNDEFINED = 2
Indicates that the measurement value is unknown for whatever reason.

dqcs_mset_contains()

Returns whether the given qubit measurement set contains data for the given qubit.

dqcs_bool_return_t dqcs_mset_contains(
    dqcs_handle_t mset,
    dqcs_qubit_t qubit
)
dqcs_mset_get()

Returns a copy of the measurement result for the given qubit from a measurement result set.

dqcs_handle_t dqcs_mset_get(
    dqcs_handle_t mset,
    dqcs_qubit_t qubit
)
dqcs_mset_len()

Returns the number of qubits measurements in the given measurement set.

ssize_t dqcs_mset_len(dqcs_handle_t mset)

This function returns -1 to indicate failure.

dqcs_mset_new()

Creates a new set of qubit measurement results.

dqcs_handle_t dqcs_mset_new(void)

Returns the handle of the newly created set. The set is initially empty.

dqcs_mset_remove()

Removes the measurement result for the given qubit from a measurement result set.

dqcs_return_t dqcs_mset_remove(
    dqcs_handle_t mset,
    dqcs_qubit_t qubit
)
dqcs_mset_set()

Adds a measurement result to a measurement result set.

dqcs_return_t dqcs_mset_set(
    dqcs_handle_t mset,
    dqcs_handle_t meas
)

If there was already a measurement for the specified qubit, the previous measurement result is overwritten. The measurement result object is deleted if and only if the function succeeds.

dqcs_mset_take()

Returns the measurement result for the given qubit from a measurement result set and removes it from the set.

dqcs_handle_t dqcs_mset_take(
    dqcs_handle_t mset,
    dqcs_qubit_t qubit
)
dqcs_mset_take_any()

Returns the measurement result for any of the qubits contained in a measurement result set and removes it from the set.

dqcs_handle_t dqcs_mset_take_any(dqcs_handle_t mset)

This is useful for iteration.

dqcs_path_style_t

Reproduction file path style.

typedef enum { ... } dqcs_path_style_t;

Variants:

DQCS_PATH_STYLE_INVALID = -1
Error value used to indicate that something went wrong.
DQCS_PATH_STYLE_KEEP = 0
Specifies that paths should be saved the same way they were specified on the command line.
DQCS_PATH_STYLE_RELATIVE = 1
Specifies that all paths should be saved relative to DQCsim's working directory.
DQCS_PATH_STYLE_ABSOLUTE = 2
Specifies that all paths should be saved canonically, i.e. relative to the root directory.

dqcs_pcfg_accept_timeout_get()

Returns the configured timeout for the plugin process to connect to DQCsim.

double dqcs_pcfg_accept_timeout_get(dqcs_handle_t pcfg)

The time unit is in seconds. Returns positive inifinity for an infinite timeout. Returns -1 when the function fails.

dqcs_pcfg_accept_timeout_set()

Configures the timeout for the plugin process to connect to DQCsim.

dqcs_return_t dqcs_pcfg_accept_timeout_set(
    dqcs_handle_t pcfg,
    double timeout
)

The default is 5 seconds, so you should normally be able to leave this alone.

The time unit is seconds. Use IEEE positive infinity to specify an infinite timeout.

dqcs_pcfg_env_set()

Overrides an environment variable for the plugin process.

dqcs_return_t dqcs_pcfg_env_set(
    dqcs_handle_t pcfg,
    const char *key,
    const char *value
)

The environment variable key is set to value regardless of whether it exists in the parent environment variable scope.

If value is NULL, the environment variable key is unset instead.

dqcs_pcfg_env_unset()

Removes/unsets an environment variable for the plugin process.

dqcs_return_t dqcs_pcfg_env_unset(
    dqcs_handle_t pcfg,
    const char *key
)

The environment variable key is unset regardless of whether it exists in the parent environment variable scope.

dqcs_pcfg_executable()

Returns the configured executable path for the given plugin process.

char *dqcs_pcfg_executable(dqcs_handle_t pcfg)

On success, this returns a newly allocated string containing the executable path. Free it with free() when you're done with it to avoid memory leaks. On failure (i.e., the handle is invalid) this returns NULL.

dqcs_pcfg_init_cmd()

Appends an ArbCmd to the list of initialization commands of a plugin process.

dqcs_return_t dqcs_pcfg_init_cmd(
    dqcs_handle_t pcfg,
    dqcs_handle_t cmd
)

The ArbCmd handle is consumed by this function, and is thus invalidated, if and only if it is successful.

dqcs_pcfg_name()

Returns the configured name for the given plugin process.

char *dqcs_pcfg_name(dqcs_handle_t pcfg)

On success, this returns a newly allocated string containing the name. Free it with free() when you're done with it to avoid memory leaks. On failure (i.e., the handle is invalid) this returns NULL.

dqcs_pcfg_new()

Creates a new plugin process configuration object using sugared syntax.

dqcs_handle_t dqcs_pcfg_new(
    dqcs_plugin_type_t typ,
    const char *name,
    const char *spec
)

typ specifies the type of plugin. name specifies the name used to refer to the plugin later, which much be unique within a simulation; if it is empty or NULL, auto-naming will be performed: "front" for the frontend, "oper<i>" for the operators (indices starting at 1 from frontend to backend), and "back" for the backend. spec specifies which plugin to use, using the same syntax that the dqcsim command line interface uses.

dqcs_pcfg_new_raw()

Creates a new plugin process configuration object using raw paths.

dqcs_handle_t dqcs_pcfg_new_raw(
    dqcs_plugin_type_t typ,
    const char *name,
    const char *executable,
    const char *script
)

This works the same as dqcs_pcfg_new(), but instead of the sugared, command-line style specification you have to specify the path to the plugin executable and (if applicable) the script it must execute directly. This is useful when you have a specific executable in mind and you don't want the somewhat heuristic desugaring algorithm from doing something unexpected.

Pass NULL or an empty string to script to specify a native plugin executable that does not take a script argument.

dqcs_pcfg_script()

Returns the configured script path for the given plugin process.

char *dqcs_pcfg_script(dqcs_handle_t pcfg)

On success, this returns a newly allocated string containing the script path. Free it with free() when you're done with it to avoid memory leaks. On failure (i.e., the handle is invalid) this returns NULL. An empty string will be returned if no script is configured to distinguish it from failure.

dqcs_pcfg_shutdown_timeout_get()

Returns the configured timeout for the plugin process to shut down gracefully.

double dqcs_pcfg_shutdown_timeout_get(dqcs_handle_t pcfg)

The time unit is in seconds. Returns positive inifinity for an infinite timeout. Returns -1 when the function fails.

dqcs_pcfg_shutdown_timeout_set()

Configures the timeout for the plugin process to shut down gracefully.

dqcs_return_t dqcs_pcfg_shutdown_timeout_set(
    dqcs_handle_t pcfg,
    double timeout
)

The default is 5 seconds, so you should normally be able to leave this alone.

The time unit is seconds. Use IEEE positive infinity to specify an infinite timeout.

dqcs_pcfg_stderr_mode_get()

Returns the configured stderr capture mode for the specified plugin process.

dqcs_loglevel_t dqcs_pcfg_stderr_mode_get(dqcs_handle_t pcfg)
dqcs_pcfg_stderr_mode_set()

Configures the capture mode for the stderr stream of the specified plugin process.

dqcs_return_t dqcs_pcfg_stderr_mode_set(
    dqcs_handle_t pcfg,
    dqcs_loglevel_t level
)
dqcs_pcfg_stdout_mode_get()

Returns the configured stdout capture mode for the specified plugin process.

dqcs_loglevel_t dqcs_pcfg_stdout_mode_get(dqcs_handle_t pcfg)
dqcs_pcfg_stdout_mode_set()

Configures the capture mode for the stdout stream of the specified plugin process.

dqcs_return_t dqcs_pcfg_stdout_mode_set(
    dqcs_handle_t pcfg,
    dqcs_loglevel_t level
)
dqcs_pcfg_tee()

Configures a plugin process to also output its log messages to a file.

dqcs_return_t dqcs_pcfg_tee(
    dqcs_handle_t pcfg,
    dqcs_loglevel_t verbosity,
    const char *filename
)

verbosity configures the verbosity level for the file only.

dqcs_pcfg_type()

Returns the type of the given plugin process configuration.

dqcs_plugin_type_t dqcs_pcfg_type(dqcs_handle_t pcfg)
dqcs_pcfg_verbosity_get()

Returns the configured verbosity for the given plugin process.

dqcs_loglevel_t dqcs_pcfg_verbosity_get(dqcs_handle_t pcfg)
dqcs_pcfg_verbosity_set()

Configures the logging verbosity for the given plugin process.

dqcs_return_t dqcs_pcfg_verbosity_set(
    dqcs_handle_t pcfg,
    dqcs_loglevel_t level
)
dqcs_pcfg_work_get()

Returns the configured working directory for the given plugin process.

char *dqcs_pcfg_work_get(dqcs_handle_t pcfg)

On success, this returns a newly allocated string containing the working directory. Free it with free() when you're done with it to avoid memory leaks. On failure (i.e., the handle is invalid) this returns NULL.

dqcs_pcfg_work_set()

Overrides the working directory for the plugin process.

dqcs_return_t dqcs_pcfg_work_set(
    dqcs_handle_t pcfg,
    const char *work
)
dqcs_pdef_author()

Returns the plugin author for the given plugin definition object.

char *dqcs_pdef_author(dqcs_handle_t pdef)

On success, this returns a newly allocated string containing the JSON string. Free it with free() when you're done with it to avoid memory leaks. On failure, this returns NULL.

dqcs_pdef_name()

Returns the plugin name for the given plugin definition object.

char *dqcs_pdef_name(dqcs_handle_t pdef)

On success, this returns a newly allocated string containing the JSON string. Free it with free() when you're done with it to avoid memory leaks. On failure, this returns NULL.

dqcs_pdef_new()

Creates a new PluginDefinition object.

dqcs_handle_t dqcs_pdef_new(
    dqcs_plugin_type_t typ,
    const char *name,
    const char *author,
    const char *version
)

Plugin definitions contain the callback functions/closures that define the functionality of a plugin. They also contain some metadata to identify the implementation, in the form of a name, author, and version string, that must be specified when the definition is constructed. The callback functions/closures are initialized to sane defaults for the requested plugin type, but obviously one or more of these should be overridden to make the plugin do something.

Once a definition object has been built, it can be used to spawn a plugin thread or run a plugin in the main thread, given a DQCsim server URL for it to connect to.

dqcs_pdef_set_advance_cb()

Sets the callback for advancing time for operators and backends.

dqcs_return_t dqcs_pdef_set_advance_cb(
    dqcs_handle_t pdef,
    dqcs_return_t (*callback)(
        void *user_data,
        dqcs_plugin_state_t state,
        dqcs_cycle_t cycles
    ),
    void (*user_free)(void *user_data),
    void *user_data
)

The default behavior for operators is to pass through to dqcs_plugin_advance(). The default for backends is no-op. This callback is never called for frontend plugins.

Besides the common arguments, the callback receives an unsigned integer specifying the number of cycles to advance by.

The callback can return an error by setting an error message using dqcs_error_set() and returning DQCS_FAILURE. Otherwise, it should return DQCS_SUCCESS.

dqcs_pdef_set_allocate_cb()

Sets the qubit allocation callback for operators and backends.

dqcs_return_t dqcs_pdef_set_allocate_cb(
    dqcs_handle_t pdef,
    dqcs_return_t (*callback)(
        void *user_data,
        dqcs_plugin_state_t state,
        dqcs_handle_t qubits,
        dqcs_handle_t alloc_cmds
    ),
    void (*user_free)(void *user_data),
    void *user_data
)

The default for operators is to pass through to dqcs_plugin_allocate(). The default for backends is no-op. This callback is never called for frontend plugins.

Besides the common arguments, the callback receives a handle to a qubit set containing the references that are to be used for the to-be-allocated qubits and an ArbCmd queue containing user-defined commands to optionally augment the behavior of the qubits. These are borrowed handles; the caller will delete them.

The callback can return an error by setting an error message using dqcs_error_set() and returning DQCS_FAILURE. Otherwise, it should return DQCS_SUCCESS.

dqcs_pdef_set_drop_cb()

Sets the user logic drop/cleanup callback.

dqcs_return_t dqcs_pdef_set_drop_cb(
    dqcs_handle_t pdef,
    dqcs_return_t (*callback)(
        void *user_data,
        dqcs_plugin_state_t state
    ),
    void (*user_free)(void *user_data),
    void *user_data
)

This is called when a plugin is gracefully terminated. It is not recommended to execute any downstream instructions at this time, but it is supported in case this is really necessary.

The default behavior is no-op.

The callback can return an error by setting an error message using dqcs_error_set() and returning DQCS_FAILURE. Otherwise, it should return DQCS_SUCCESS.

dqcs_pdef_set_free_cb()

Sets the qubit deallocation callback for operators and backends.

dqcs_return_t dqcs_pdef_set_free_cb(
    dqcs_handle_t pdef,
    dqcs_return_t (*callback)(
        void *user_data,
        dqcs_plugin_state_t state,
        dqcs_handle_t qubits
    ),
    void (*user_free)(void *user_data),
    void *user_data
)

The default for operators is to pass through to dqcs_plugin_free(). The default for backends is no-op. This callback is never called for frontend plugins.

Besides the common arguments, the callback receives a handle to a qubit set containing the qubits that are to be freed. This is a borrowed handle; the caller will delete it.

The callback can return an error by setting an error message using dqcs_error_set() and returning DQCS_FAILURE. Otherwise, it should return DQCS_SUCCESS.

dqcs_pdef_set_gate_cb()

Sets the gate execution callback for operators and backends.

dqcs_return_t dqcs_pdef_set_gate_cb(
    dqcs_handle_t pdef,
    dqcs_handle_t (*callback)(
        void *user_data,
        dqcs_plugin_state_t state,
        dqcs_handle_t gate
    ),
    void (*user_free)(void *user_data),
    void *user_data
)

Besides the common arguments, the callback receives a handle to the to-be-executed gate. This is a borrowed handle; the caller will delete it.

The callback must return one of the following things:

  • a valid handle to a measurement set, created using dqcs_mset_new() (this object is automatically deleted after the callback returns);
  • a valid handle to a single qubit measurement, created using dqcs_meas_new() (this object is automatically deleted after the callback returns);
  • the handle to the supplied gate, a shortcut for not returning any measurements (this is less clear than returning an empty measurement set, but slightly faster); or
  • 0 to report an error, after calling the error string using dqcs_set_error().

Backend plugins must return a measurement result set containing exactly those qubits specified in the measurement set. For operators, however, the story is more complicated. Let's say we want to make a silly operator that inverts all measurements. The trivial way to do this would be to forward the gate, query all the measurement results using dqcs_plugin_get_measurement(), invert them, stick them in a measurement result set, and return that result set. However, this approach is not very efficient, because dqcs_plugin_get_measurement() has to wait for all downstream plugins to finish executing the gate, forcing the OS to switch threads, etc. Instead, operators are allowed to return only a subset (or none) of the measured qubits, as long as they return the measurements as they arrive through the modify_measurement() callback.

The default implementation for this callback for operators is to pass the gate through to the downstream plugin and return an empty set of measurements. Combined with the default implementation of modify_measurement(), this behavior is sane. Backends must override this callback; the default is to return a not-implemented error.

Note that for our silly example operator, the default behavior for this function is sufficient; you'd only have to override modify_measurement() to, well, modify the measurements.

dqcs_pdef_set_host_arb_cb()

Sets the callback function function for handling an arb from the host.

dqcs_return_t dqcs_pdef_set_host_arb_cb(
    dqcs_handle_t pdef,
    dqcs_handle_t (*callback)(
        void *user_data,
        dqcs_plugin_state_t state,
        dqcs_handle_t cmd
    ),
    void (*user_free)(void *user_data),
    void *user_data
)

The default behavior for this is no-op.

Besides the common arguments, the callback receives a handle to the ArbCmd object representing the request. It must return a valid ArbData handle containing the response. Both objects are deleted automatically after invocation.

The callback can return an error by setting an error message using dqcs_error_set() and returning 0. Otherwise, it should return a valid ArbData handle.

dqcs_pdef_set_initialize_cb()

Sets the user logic initialization callback.

dqcs_return_t dqcs_pdef_set_initialize_cb(
    dqcs_handle_t pdef,
    dqcs_return_t (*callback)(
        void *user_data,
        dqcs_plugin_state_t state,
        dqcs_handle_t init_cmds
    ),
    void (*user_free)(void *user_data),
    void *user_data
)

This is always called before any of the other callbacks are run. The downstream plugin has already been initialized at this stage, so it is legal to send it commands.

The default behavior is no-op.

Besides the common arguments, the callback receives a handle to an ArbCmd queue (dqcs_cq_*, dqcs_cmd_*, and dqcs_arb_* interfaces) containing user-defined initialization commands. This is a borrowed handle; the caller will delete it.

The callback can return an error by setting an error message using dqcs_error_set() and returning DQCS_FAILURE. Otherwise, it should return DQCS_SUCCESS.

dqcs_pdef_set_modify_measurement_cb()

Sets the measurement modification callback for operators.

dqcs_return_t dqcs_pdef_set_modify_measurement_cb(
    dqcs_handle_t pdef,
    dqcs_handle_t (*callback)(
        void *user_data,
        dqcs_plugin_state_t state,
        dqcs_handle_t meas
    ),
    void (*user_free)(void *user_data),
    void *user_data
)

This callback is called for every measurement result received from the downstream plugin, and returns the measurements that should be reported to the upstream plugin. Note that the results from our plugin's dqcs_plugin_get_measurement() and friends are consistent with the results received from downstream; they are not affected by this function.

The callback takes a handle to a single qubit measurement object as an argument, and must return one of the following things:

  • a valid handle to a measurement set, created using dqcs_mset_new() (this object is automatically deleted after the callback returns);
  • a valid handle to a single qubit measurement object, which may or may not be the supplied one (this object is automatically deleted after the callback returns); or
  • 0 to report an error, after calling the error string using dqcs_set_error().

This callback is somewhat special in that it is not allowed to call any plugin command other than logging and the pseudorandom number generator functions. This is because this function is called asynchronously with respect to the downstream functions, making the timing of these calls non-deterministic based on operating system scheduling.

Note that while this function is called for only a single measurement at a time, it is allowed to produce a vector of measurements. This allows you to cancel propagation of the measurement by returning an empty vector, to just modify the measurement data itself, or to generate additional measurements from a single measurement. However, if you need to modify the qubit references for operators that remap qubits, take care to only send measurement data upstream when these were explicitly requested through the associated upstream gate function's measured list.

The default behavior for this callback is to return the measurement without modification.

dqcs_pdef_set_run_cb()

Sets the run callback for frontends.

dqcs_return_t dqcs_pdef_set_run_cb(
    dqcs_handle_t pdef,
    dqcs_handle_t (*callback)(
        void *user_data,
        dqcs_plugin_state_t state,
        dqcs_handle_t args
    ),
    void (*user_free)(void *user_data),
    void *user_data
)

This is called in response to a start() host API call. The return value is returned through the wait() host API call.

The default behavior is to fail with a "not implemented" error; frontends backends should always override this. This callback is never called for operator or backend plugins.

Besides the common arguments, the callback receives a handle to an ArbData object containing the data that the host passed to start(). This is a borrowed handle; the caller will delete it.

When the run callback is successful, it should return a valid ArbData handle. This can be the same as the argument, but it can also be a new object. This ArbData is returned to the host through wait(). This ArbData object is deleted after the callback completes.

The callback can return an error by setting an error message using dqcs_error_set() and returning 0. Otherwise, it should return a valid ArbData handle.

dqcs_pdef_set_upstream_arb_cb()

Sets the callback function for handling an arb from upstream for operators and backends.

dqcs_return_t dqcs_pdef_set_upstream_arb_cb(
    dqcs_handle_t pdef,
    dqcs_handle_t (*callback)(
        void *user_data,
        dqcs_plugin_state_t state,
        dqcs_handle_t cmd
    ),
    void (*user_free)(void *user_data),
    void *user_data
)

The default behavior for operators is to pass through to dqcs_plugin_arb(); operators that do not support the requested interface should always do this. The default for backends is no-op. This callback is never called for frontend plugins.

Besides the common arguments, the callback receives a handle to the ArbCmd object representing the request. It must return a valid ArbData handle containing the response. Both objects are deleted automatically after invocation.

The callback can return an error by setting an error message using dqcs_error_set() and returning 0. Otherwise, it should return a valid ArbData handle.

dqcs_pdef_type()

Returns the plugin type for the given plugin definition object.

dqcs_plugin_type_t dqcs_pdef_type(dqcs_handle_t pdef)
dqcs_pdef_version()

Returns the plugin version for the given plugin definition object.

char *dqcs_pdef_version(dqcs_handle_t pdef)

On success, this returns a newly allocated string containing the JSON string. Free it with free() when you're done with it to avoid memory leaks. On failure, this returns NULL.

dqcs_plugin_advance()

Tells the downstream plugin to run for the specified number of cycles.

dqcs_cycle_t dqcs_plugin_advance(
    dqcs_plugin_state_t plugin,
    dqcs_cycle_t cycles
)

Backend plugins are not allowed to call this. Doing so will result in an error.

The return value is the new cycle counter. This function uses -1 to signal an error.

dqcs_plugin_allocate()

Allocate the given number of downstream qubits.

dqcs_handle_t dqcs_plugin_allocate(
    dqcs_plugin_state_t plugin,
    uintptr_t num_qubits,
    dqcs_handle_t cq
)

Backend plugins are not allowed to call this. Doing so will result in an error.

num_qubits specifies the number of qubits that are to be allocated.

commands must be 0 or a valid handle to an ArbCmd queue, containing a list of commands that may be used to modify the behavior of the qubit register; 0 is equivalent to zero commands. The queue is consumed by this function, i.e. the handle becomes invalid, if and only if it succeeds.

If the function is successful, a new handle to the set of qubit references representing the newly allocated register is returned. When the function fails, 0 is returned.

dqcs_plugin_arb()

Sends an arbitrary command downstream.

dqcs_handle_t dqcs_plugin_arb(
    dqcs_plugin_state_t plugin,
    dqcs_handle_t cmd
)

Backend plugins are not allowed to call this. Doing so will result in an error.

This function returns a new handle to an ArbData object representing the return value of the ArbCmd when successful. Otherwise, it returns 0.

dqcs_plugin_free()

Free the given downstream qubits.

dqcs_return_t dqcs_plugin_free(
    dqcs_plugin_state_t plugin,
    dqcs_handle_t qbset
)

Backend plugins are not allowed to call this. Doing so will result in an error.

qubits must be a valid set of qubit references. The set is consumed by this function, i.e. the handle becomes invalid, if and only if it succeeds.

dqcs_plugin_gate()

Tells the downstream plugin to execute a gate.

dqcs_return_t dqcs_plugin_gate(
    dqcs_plugin_state_t plugin,
    dqcs_handle_t gate
)

Backend plugins are not allowed to call this. Doing so will result in an error.

gate must be a valid gate object. The object is consumed by this function, i.e. the handle becomes invalid, if and only if it succeeds.

dqcs_plugin_get_cycle()

Returns the current value of the downstream cycle counter.

dqcs_cycle_t dqcs_plugin_get_cycle(dqcs_plugin_state_t plugin)

Backend plugins are not allowed to call this. Doing so will result in an error.

This function uses -1 to signal an error.

dqcs_plugin_get_cycles_between_measures()

Returns the number of downstream cycles between the last two measurements of the given downstream qubit.

dqcs_cycle_t dqcs_plugin_get_cycles_between_measures(
    dqcs_plugin_state_t plugin,
    dqcs_qubit_t qubit
)

Backend plugins are not allowed to call this. Doing so will result in an error.

This function uses -1 to signal an error.

dqcs_plugin_get_cycles_since_measure()

Returns the number of downstream cycles since the latest measurement of the given downstream qubit.

dqcs_cycle_t dqcs_plugin_get_cycles_since_measure(
    dqcs_plugin_state_t plugin,
    dqcs_qubit_t qubit
)

Backend plugins are not allowed to call this. Doing so will result in an error.

This function uses -1 to signal an error.

dqcs_plugin_get_measurement()

Returns the latest measurement of the given downstream qubit.

dqcs_handle_t dqcs_plugin_get_measurement(
    dqcs_plugin_state_t plugin,
    dqcs_qubit_t qubit
)

Backend plugins are not allowed to call this. Doing so will result in an error.

If the function succeeds, it returns a new handle to a qubit measurement result object. Otherwise it returns 0.

dqcs_plugin_random_f64()

Generates a random floating point number using the simulator random seed.

double dqcs_plugin_random_f64(dqcs_plugin_state_t plugin)

The generated numbers are uniformly distributed in the range [0,1>.

This function only fails if the plugin handle is invalid, in which case it returns 0. Of course, 0 is also a valid (if rare) random return value.

dqcs_plugin_random_u64()

Generates a random unsigned 64-bit number using the simulator random seed.

dqcs_handle_t dqcs_plugin_random_u64(dqcs_plugin_state_t plugin)

This function only fails if the plugin handle is invalid, in which case it returns 0. Of course, 0 is also a valid (if rare) random return value.

dqcs_plugin_recv()

Waits for a message from the host.

dqcs_handle_t dqcs_plugin_recv(dqcs_plugin_state_t plugin)

It is only legal to call this function from within the run() callback. Any other source will result in an error.

When successful, this function returns a new handle to the received ArbData object. 0 is used to indicate that an error occurred.

dqcs_plugin_run()

Executes a plugin in the current thread.

dqcs_return_t dqcs_plugin_run(
    dqcs_handle_t pdef,
    const char *simulator
)

pdef must be an appropriately populated plugin definition object. Its callback functions will be called from the current thread, from within the context of this function.

simulator must be set to the address of our endpoint of the simulator that's using the plugin; DQCsim normally passes this as the first command line argument of the plugin process.

If the plugin starts, the pdef handle is consumed by this function, regardless of whether the plugin eventually closes normally. The handle is only left alive if pdef is not a plugin definition object.

dqcs_plugin_send()

Sends a message to the host.

dqcs_return_t dqcs_plugin_send(
    dqcs_plugin_state_t plugin,
    dqcs_handle_t arb
)

It is only legal to call this function from within the run() callback. Any other source will result in an error.

The cmd handle is consumed by this function if and only if it succeeds.

dqcs_plugin_start()

Executes a plugin in a worker thread.

dqcs_handle_t dqcs_plugin_start(
    dqcs_handle_t pdef,
    const char *simulator
)

This function behaves the same as dqcs_plugin_log(), but is asynchronous; it always returns immediately. Of course, this means that the callbacks in pdef will be called from a different thread.

To wait for the thread to finish executing, call dqcs_plugin_wait() on the returned join handle. Alternatively you can delete the join handle object, which will detach the thread.

Note that dqcs_log_*() will only be available in the thread that the plugin actually runs in.

This function returns 0 to indicate failure to start the plugin. Otherwise, the join handle is returned.

dqcs_plugin_state_t

Type for a plugin state.

typedef void *dqcs_plugin_state_t;

This is an opaque type that is passed along to plugin implementation callback functions, which those callbacks can then use to interact with the plugin instance. User code shall not create or modify values of this type, and shall only use the values when calling dqcs_plugin_* functions.

dqcs_plugin_type_t

Enumeration of the three types of plugins.

typedef enum { ... } dqcs_plugin_type_t;

Variants:

DQCS_PTYPE_INVALID = -1
Invalid plugin type. Used to indicate failure of an API that returns a plugin type.
DQCS_PTYPE_FRONT = 0
Frontend plugin.
DQCS_PTYPE_OPER = 1
Operator plugin.
DQCS_PTYPE_BACK = 2
Backend plugin.

dqcs_plugin_wait()

Waits for a plugin worker thread to finish executing.

dqcs_return_t dqcs_plugin_wait(dqcs_handle_t pjoin)

Unless the join handle is invalid, this function returns success/failure based on the result of the plugin execution. If the plugin thread is joined, the join handle is deleted.

dqcs_predefined_gate_t

Enumeration of gates defined by DQCsim.

typedef enum { ... } dqcs_predefined_gate_t;

Variants:

DQCS_GATE_INVALID = 0
Invalid gate. Used as an error return value.
DQCS_GATE_PAULI_I = 100
The identity gate for a single qubit.

\[ I = \sigma_0 = \begin{bmatrix} 1 & 0 \\ 0 & 1 \end{bmatrix} \]

DQCS_GATE_PAULI_X = 101
The Pauli X matrix.

\[ X = \sigma_1 = \begin{bmatrix} 0 & 1 \\ 1 & 0 \end{bmatrix} \]

DQCS_GATE_PAULI_Y = 102
The Pauli Y matrix.

\[ Y = \sigma_2 = \begin{bmatrix} 0 & -i \\ i & 0 \end{bmatrix} \]

DQCS_GATE_PAULI_Z = 103
The Pauli Z matrix.

\[ Z = \sigma_3 = \begin{bmatrix} 1 & 0 \\ 0 & -1 \end{bmatrix} \]

DQCS_GATE_H = 104
The hadamard gate matrix. That is, a 180-degree Y rotation, followed by a 90-degree X rotation.

\[ H = \frac{1}{\sqrt{2}} \begin{bmatrix} 1 & 1 \\ 1 & -1 \end{bmatrix} \]

DQCS_GATE_S = 105
The S matrix, also known as a 90 degree Z rotation.

\[ S = \begin{bmatrix} 1 & 0 \\ 0 & i \end{bmatrix} \]

DQCS_GATE_S_DAG = 106
The S-dagger matrix, also known as a negative 90 degree Z rotation.

\[ S^\dagger = \begin{bmatrix} 1 & 0 \\ 0 & -i \end{bmatrix} \]

DQCS_GATE_T = 107
The T matrix, also known as a 45 degree Z rotation.

\[ T = \begin{bmatrix} 1 & 0 \\ 0 & e^{i\frac{\pi}{4}} \end{bmatrix} \]

DQCS_GATE_T_DAG = 108
The T-dagger matrix, also known as a negative 45 degree Z rotation.

\[ T^\dagger = \begin{bmatrix} 1 & 0 \\ 0 & e^{-i\frac{\pi}{4}} \end{bmatrix} \]

DQCS_GATE_RX_90 = 109
Rx(90°) gate.

\[ R_x\left(\frac{\pi}{2}\right) = \frac{1}{\sqrt{2}} \begin{bmatrix} 1 & -i \\ -i & 1 \end{bmatrix} \]

DQCS_GATE_RX_M90 = 110
Rx(-90°) gate.

\[ R_x\left(-\frac{\pi}{2}\right) = \frac{1}{\sqrt{2}} \begin{bmatrix} 1 & i \\ i & 1 \end{bmatrix} \]

DQCS_GATE_RX_180 = 111
Rx(180°) gate.

\[ R_x(\pi) = \begin{bmatrix} 0 & -i \\ -i & 0 \end{bmatrix} \]

This matrix is equivalent to the Pauli X gate, but differs in global phase. Note that this difference is significant when it is used as a submatrix for a controlled gate.

DQCS_GATE_RY_90 = 112
Ry(90°) gate.

\[ R_y\left(\frac{\pi}{2}\right) = \frac{1}{\sqrt{2}} \begin{bmatrix} 1 & -1 \\ 1 & 1 \end{bmatrix} \]

DQCS_GATE_RY_M90 = 113
Ry(-90°) gate.

\[ R_y\left(\frac{\pi}{2}\right) = \frac{1}{\sqrt{2}} \begin{bmatrix} 1 & 1 \\ -1 & 1 \end{bmatrix} \]

DQCS_GATE_RY_180 = 114
Ry(180°) gate.

\[ R_y(\pi) = \begin{bmatrix} 0 & -1 \\ 1 & 0 \end{bmatrix} \]

This matrix is equivalent to the Pauli Y gate, but differs in global phase. Note that this difference is significant when it is used as a submatrix for a controlled gate.

DQCS_GATE_RZ_90 = 115
Rz(90°) gate.

\[ R_z\left(\frac{\pi}{2}\right) = \frac{1}{\sqrt{2}} \begin{bmatrix} 1-i & 0 \\ 0 & 1+i \end{bmatrix} \]

This matrix is equivalent to the S gate, but differs in global phase. Note that this difference is significant when it is used as a submatrix for a controlled gate.

DQCS_GATE_RZ_M90 = 116
Rz(-90°) gate.

\[ R_z\left(-\frac{\pi}{2}\right) = \frac{1}{\sqrt{2}} \begin{bmatrix} 1+i & 0 \\ 0 & 1-i \end{bmatrix} \]

This matrix is equivalent to the S-dagger gate, but differs in global phase. Note that this difference is significant when it is used as a submatrix for a controlled gate.

DQCS_GATE_RZ_180 = 117
Rz(180°) gate.

\[ R_z(\pi) = \begin{bmatrix} -i & 0 \\ 0 & i \end{bmatrix} \]

This matrix is equivalent to the Pauli Z gate, but differs in global phase. Note that this difference is significant when it is used as a submatrix for a controlled gate.

DQCS_GATE_RX = 150
The matrix for an arbitrary X rotation.

\[ R_x(\theta) = \begin{bmatrix} \cos{\frac{\theta}{2}} & -i\sin{\frac{\theta}{2}} \\ -i\sin{\frac{\theta}{2}} & \cos{\frac{\theta}{2}} \end{bmatrix} \]

θ is specified or returned through the first binary string argument of the parameterization ArbData object. It is represented as a little-endian double floating point value, specified in radians.

DQCS_GATE_RY = 151
The matrix for an arbitrary Y rotation.

\[ R_y(\theta) = \begin{bmatrix} \cos{\frac{\theta}{2}} & -\sin{\frac{\theta}{2}} \\ \sin{\frac{\theta}{2}} & \cos{\frac{\theta}{2}} \end{bmatrix} \]

θ is specified or returned through the first binary string argument of the parameterization ArbData object. It is represented as a little-endian double floating point value, specified in radians.

DQCS_GATE_RZ = 152
The matrix for an arbitrary Z rotation.

\[ R_z(\theta) = \begin{bmatrix} e^{-i\frac{\theta}{2}} & 0 \\ 0 & e^{i\frac{\theta}{2}} \end{bmatrix} \]

θ is specified or returned through the first binary string argument of the parameterization ArbData object. It is represented as a little-endian double floating point value, specified in radians.

DQCS_GATE_PHASE_K = 153
The matrix for a Z rotation with angle π/2^k.

\[ \textit{PhaseK}(k) = \textit{Phase}\left(\frac{\pi}{2^k}\right) = \begin{bmatrix} 1 & 0 \\ 0 & e^{i\pi / 2^k} \end{bmatrix} \]

k is specified or returned through the first binary string argument of the parameterization ArbData object. It is represented as a little-endian unsigned 64-bit integer.

DQCS_GATE_PHASE = 154
The matrix for an arbitrary Z rotation.

\[ \textit{Phase}(\theta) = \begin{bmatrix} 1 & 0 \\ 0 & e^{i\theta} \end{bmatrix} \]

θ is specified or returned through the first binary string argument of the parameterization ArbData object. It is represented as a little-endian double floating point value, specified in radians.

This matrix is equivalent to the Rz gate, but differs in global phase. Note that this difference is significant when it is used as a submatrix for a controlled gate. Specifically, controlled phase gates use the phase as specified by this gate, whereas Rz follows the usual algebraic notation.

DQCS_GATE_U1 = 190
Any single-qubit unitary gate, parameterized as a full unitary matrix.

The full matrix is specified or returned through the first binary string argument of the parameterization ArbData object. It is represented as an array of little-endian double floating point values, structured as real/imag pairs, with the pairs in row-major order.

DQCS_GATE_R = 191
Arbitrary rotation matrix.

\[ R(\theta, \phi, \lambda) = \begin{bmatrix} \cos{\frac{\theta}{2}} & -\sin{\frac{\theta}{2}} e^{i\lambda} \\ \sin{\frac{\theta}{2}} e^{i\phi} & \cos{\frac{\theta}{2}} e^{i\phi + i\lambda} \end{bmatrix} \]

This is equivalent to the following:

\[ R(\theta, \phi, \lambda) = \textit{Phase}(\phi) \cdot R_y(\theta) \cdot \textit{Phase}(\lambda) \]

The rotation order and phase is taken from Qiskit's U3 gate. Ignoring global phase, any unitary single-qubit gate can be represented with this notation.

θ, φ, and λ are specified or returned through the first three binary string arguments of the parameterization ArbData object. They are represented as little-endian double floating point values, specified in radians.

DQCS_GATE_SWAP = 200
The swap gate matrix.

\[ \textit{SWAP} = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} \]

DQCS_GATE_SQRT_SWAP = 201
The square-root of a swap gate matrix.

\[ \sqrt{\textit{SWAP}} = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & \frac{i+1}{2} & \frac{i-1}{2} & 0 \\ 0 & \frac{i-1}{2} & \frac{i+1}{2} & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} \]

DQCS_GATE_U2 = 290
Any two-qubit unitary gate, parameterized as a full unitary matrix.

The full matrix is specified or returned through the first binary string argument of the parameterization ArbData object. It is represented as an array of little-endian double floating point values, structured as real/imag pairs, with the pairs in row-major order.

DQCS_GATE_U3 = 390
Any three-qubit unitary gate, parameterized as a full unitary matrix.

The full matrix is specified or returned through the first binary string argument of the parameterization ArbData object. It is represented as an array of little-endian double floating point values, structured as real/imag pairs, with the pairs in row-major order.

dqcs_qbset_contains()

Returns whether the given qubit set contains the given qubit.

dqcs_bool_return_t dqcs_qbset_contains(
    dqcs_handle_t qbset,
    dqcs_qubit_t qubit
)
dqcs_qbset_copy()

Returns a copy of the given qubit set, intended for non-destructive iteration.

dqcs_handle_t dqcs_qbset_copy(dqcs_handle_t qbset)
dqcs_qbset_len()

Returns the number of qubits in the given set.

ssize_t dqcs_qbset_len(dqcs_handle_t qbset)

This function returns -1 to indicate failure.

dqcs_qbset_new()

Creates a new set of qubit references.

dqcs_handle_t dqcs_qbset_new(void)

Returns the handle of the newly created set. The set is initially empty. Qubit sets are ordered, meaning that the order in which qubits are popped from the set equals the order in which they were pushed. To iterate over a set, simply make a copy and drain the copy using pop.

dqcs_qbset_pop()

Pops a qubit reference off of a qubit reference set.

dqcs_qubit_t dqcs_qbset_pop(dqcs_handle_t qbset)

Qubits are popped in the same order in which they were pushed. That is, they are FIFO-ordered.

dqcs_qbset_push()

Pushes a qubit reference into a qubit reference set.

dqcs_return_t dqcs_qbset_push(
    dqcs_handle_t qbset,
    dqcs_qubit_t qubit
)

This function will fail if the specified qubit was already part of the set.

dqcs_qubit_t

Type for a qubit reference.

typedef unsigned long long dqcs_qubit_t;

Qubit references are exchanged between the frontend, operator, and backend plugins to indicate which qubits a gate operates on. Note that this makes them fundamentally different from handles, which are thread-local.

Qubit references are always positive integers, counting upwards from 1 upon allocation, and they are not reused even after the qubit is deallocated. Thus, every subsequent allocation returns a qubit reference one greater than the previous. This is guaranteed behavior that external code can rely upon. The value zero is reserved for invalid references or error propagation.

dqcs_return_t

Default return type for functions that don't need to return anything.

typedef enum { ... } dqcs_return_t;

Variants:

DQCS_FAILURE = -1
The function has failed. More information may be obtained through `dqcsim_explain()`.
DQCS_SUCCESS = 0
The function did what it was supposed to.

dqcs_scfg_dqcsim_verbosity_get()

Returns the configured verbosity for DQCsim's own messages.

dqcs_loglevel_t dqcs_scfg_dqcsim_verbosity_get(dqcs_handle_t scfg)
dqcs_scfg_dqcsim_verbosity_set()

Configures the logging verbosity for DQCsim's own messages.

dqcs_return_t dqcs_scfg_dqcsim_verbosity_set(
    dqcs_handle_t scfg,
    dqcs_loglevel_t level
)
dqcs_scfg_log_callback()

Configures DQCsim to also output its log messages to callback function.

dqcs_return_t dqcs_scfg_log_callback(
    dqcs_handle_t scfg,
    dqcs_loglevel_t verbosity,
    void (*callback)(
        void *user_data,
        const char *message,
        const char *logger,
        dqcs_loglevel_t level,
        const char *module,
        const char *file,
        uint32_t line,
        uint64_t time_s,
        uint32_t time_ns,
        uint32_t pid,
        uint64_t tid
    ),
    void (*user_free)(void *user_data),
    void *user_data
)

verbosity specifies the minimum importance of a message required for the callback to be called.

callback is the callback function to install. It is always called with the user_data pointer to make calling stuff like class member functions or closures possible. The user_free function, if non-null, will be called when the callback is uninstalled in any way. If callback is null, any current callback is uninstalled instead. For consistency, if user_free is non-null while callback is null, user_free is called immediately, under the assumption that the caller has allocated resources unbeknownst that the callback it's trying to install is null.

NOTE: both callback and user_free may be called from a thread spawned by the simulator. Calling any API calls from the callback is therefore undefined behavior!

The callback takes the following arguments:

  • void*: user defined data.
  • const char*: log message string, excluding metadata.
  • const char*: name assigned to the logger that was used to produce the message (= "dqcsim" or a plugin name).
  • dqcs_loglevel_t: the verbosity level that the message was logged with.
  • const char*: string representing the source of the log message, or NULL when no source is known.
  • const char*: string containing the filename of the source that generated the message, or NULL when no source is known.
  • uint32_t: line number within the aforementioned file, or 0 if not known.
  • uint64_t: Time in seconds since the Unix epoch.
  • uint32_t: Additional time in nanoseconds since the aforementioned.
  • uint32_t: PID of the generating process.
  • uint64_t: TID of the generating thread.

If an internal log record is particularly malformed and cannot be coerced into the above (nul bytes in the strings, invalid timestamp, whatever) the message is silently ignored.

The primary use of this callback is to pipe DQCsim's messages to an external logging framework. When you do this, you probably also want to call dqcs_scfg_stderr_verbosity_set(handle, DQCS_LOG_OFF) to prevent DQCsim from writing the messages to stderr itself.

dqcs_scfg_new()

Constructs an empty simulation configuration.

dqcs_handle_t dqcs_scfg_new(void)

Before the configuration can be used, at least a frontend and a backend plugin configuration must be pushed into it. This can be done with dqcs_scfg_push_plugin(). Failing to do this will result in an error when you try to start the simulation.

The default settings correspond to the defaults of the dqcsim command line interface. Refer to its help for more information.

dqcs_scfg_push_plugin()

Appends a plugin to a simulation configuration.

dqcs_return_t dqcs_scfg_push_plugin(
    dqcs_handle_t scfg,
    dqcs_handle_t xcfg
)

Both plugin process and plugin thread configuration objects may be used. The handle is consumed by this function, and is thus invalidated, if and only if it is successful.

Frontend and backend plugins will automatically be inserted at the front and back of the pipeline when the simulation is created. Operators are inserted in front to back order. This function does not provide safeguards against multiple frontends/backends; such errors will only be reported when the simulation is started.

Note that it is not possible to observe or mutate a plugin configuration once it has been added to a simulator configuration handle. If you want to do this for some reason, you should maintain your own data structures, and only build the DQCsim structures from them when you're done.

dqcs_scfg_repro_disable()

Disables the reproduction logging system.

dqcs_return_t dqcs_scfg_repro_disable(dqcs_handle_t scfg)

Calling this will disable the warnings printed when a simulation that cannot be reproduced is constructed.

dqcs_scfg_repro_path_style_get()

Returns the path style used when writing reproduction files.

dqcs_path_style_t dqcs_scfg_repro_path_style_get(dqcs_handle_t scfg)
dqcs_scfg_repro_path_style_set()

Sets the path style used when writing reproduction files.

dqcs_return_t dqcs_scfg_repro_path_style_set(
    dqcs_handle_t scfg,
    dqcs_path_style_t path_style
)
dqcs_scfg_seed_get()

Returns the configured random seed.

uint64_t dqcs_scfg_seed_get(dqcs_handle_t scfg)

This function will return 0 when it fails, but this can unfortunately not be reliably distinguished from a seed that was set to 0.

dqcs_scfg_seed_set()

Configures the random seed that the simulation should use.

dqcs_return_t dqcs_scfg_seed_set(
    dqcs_handle_t scfg,
    uint64_t seed
)

Note that the seed is randomized by default.

dqcs_scfg_stderr_verbosity_get()

Returns the configured stderr sink verbosity for a simulation.

dqcs_loglevel_t dqcs_scfg_stderr_verbosity_get(dqcs_handle_t scfg)

That is, the minimum loglevel that a messages needs to have for it to be printed to stderr.

dqcs_scfg_stderr_verbosity_set()

Configures the stderr sink verbosity for a simulation.

dqcs_return_t dqcs_scfg_stderr_verbosity_set(
    dqcs_handle_t scfg,
    dqcs_loglevel_t level
)

That is, the minimum loglevel that a messages needs to have for it to be printed to stderr.

dqcs_scfg_tee()

Configures DQCsim to also output its log messages to a file.

dqcs_return_t dqcs_scfg_tee(
    dqcs_handle_t scfg,
    dqcs_loglevel_t verbosity,
    const char *filename
)

verbosity configures the verbosity level for the file only.

dqcs_sim_arb()

Sends an ArbCmd message to one of the plugins, referenced by name.

dqcs_handle_t dqcs_sim_arb(
    dqcs_handle_t sim,
    const char *name,
    dqcs_handle_t cmd
)

ArbCmds are executed immediately after yielding to the simulator, so all pending asynchronous calls are flushed and executed before the ArbCmd.

When this succeeds, the received data is returned in the form of a new handle. When it fails, 0 is returned.

The ArbCmd handle is consumed if and only if the API call succeeds.

dqcs_sim_arb_idx()

Sends an ArbCmd message to one of the plugins, referenced by index.

dqcs_handle_t dqcs_sim_arb_idx(
    dqcs_handle_t sim,
    ssize_t index,
    dqcs_handle_t cmd
)

The frontend always has index 0. 1 through N are used for the operators in front to back order (where N is the number of operators). The backend is at index N+1.

Python-style negative indices are supported. That is, -1 can be used to refer to the backend, -2 to the last operator, and so on.

ArbCmds are executed immediately after yielding to the simulator, so all pending asynchronous calls are flushed and executed before the ArbCmd.

When this succeeds, the received data is returned in the form of a new handle. When it fails, 0 is returned.

The ArbCmd handle is consumed if and only if the API call succeeds.

dqcs_sim_get_author()

Queries the author of a plugin, referenced by instance name.

char *dqcs_sim_get_author(
    dqcs_handle_t sim,
    const char *name
)

On success, this returns a newly allocated string containing the author. Free it with free() when you're done with it to avoid memory leaks. On failure (i.e., the handle is invalid) this returns NULL.

dqcs_sim_get_author_idx()

Queries the author of a plugin, referenced by index.

char *dqcs_sim_get_author_idx(
    dqcs_handle_t sim,
    ssize_t index
)

On success, this returns a newly allocated string containing the author. Free it with free() when you're done with it to avoid memory leaks. On failure (i.e., the handle is invalid) this returns NULL.

dqcs_sim_get_name()

Queries the implementation name of a plugin, referenced by instance name.

char *dqcs_sim_get_name(
    dqcs_handle_t sim,
    const char *name
)

On success, this returns a newly allocated string containing the name. Free it with free() when you're done with it to avoid memory leaks. On failure (i.e., the handle is invalid) this returns NULL.

dqcs_sim_get_name_idx()

Queries the implementation name of a plugin, referenced by index.

char *dqcs_sim_get_name_idx(
    dqcs_handle_t sim,
    ssize_t index
)

On success, this returns a newly allocated string containing the name. Free it with free() when you're done with it to avoid memory leaks. On failure (i.e., the handle is invalid) this returns NULL.

dqcs_sim_get_version()

Queries the version of a plugin, referenced by instance name.

char *dqcs_sim_get_version(
    dqcs_handle_t sim,
    const char *name
)

On success, this returns a newly allocated string containing the version. Free it with free() when you're done with it to avoid memory leaks. On failure (i.e., the handle is invalid) this returns NULL.

dqcs_sim_get_version_idx()

Queries the version of a plugin, referenced by index.

char *dqcs_sim_get_version_idx(
    dqcs_handle_t sim,
    ssize_t index
)

On success, this returns a newly allocated string containing the version. Free it with free() when you're done with it to avoid memory leaks. On failure (i.e., the handle is invalid) this returns NULL.

dqcs_sim_new()

Constructs a DQCsim simulation.

dqcs_handle_t dqcs_sim_new(dqcs_handle_t scfg)

The provided handle is consumed if it is a simulation configuration, regardless of whether simulation construction succeeds.

dqcs_sim_recv()

Waits for the simulated accelerator to send a message to us.

dqcs_handle_t dqcs_sim_recv(dqcs_handle_t sim)

When this succeeds, the received data is returned in the form of a new handle. When it fails, 0 is returned.

Deadlocks are detected and prevented by returning an error.

dqcs_sim_send()

Sends a message to the simulated accelerator.

dqcs_return_t dqcs_sim_send(
    dqcs_handle_t sim,
    dqcs_handle_t data
)

This is an asynchronous call: nothing happens until yield(), recv(), or wait() is called.

The ArbData handle is optional; if 0 is passed, an empty data object is used. If a handle is passed, it is consumed if and only if the API call succeeds.

dqcs_sim_start()

Starts a program on the simulated accelerator.

dqcs_return_t dqcs_sim_start(
    dqcs_handle_t sim,
    dqcs_handle_t data
)

This is an asynchronous call: nothing happens until yield(), recv(), or wait() is called.

The ArbData handle is optional; if 0 is passed, an empty data object is used. If a handle is passed, it is consumed if and only if the API call succeeds.

dqcs_sim_wait()

Waits for the simulated accelerator to finish its current program.

dqcs_handle_t dqcs_sim_wait(dqcs_handle_t sim)

When this succeeds, the return value of the accelerator's run() function is returned in the form of a new handle. When it fails, 0 is returned.

Deadlocks are detected and prevented by returning an error.

dqcs_sim_write_reproduction_file()

Writes a reproduction file for the simulation so far.

dqcs_return_t dqcs_sim_write_reproduction_file(
    dqcs_handle_t sim,
    const char *filename
)
dqcs_sim_yield()

Yields to the simulator.

dqcs_return_t dqcs_sim_yield(dqcs_handle_t sim)

The simulation runs until it blocks again. This is useful if you want an immediate response to an otherwise asynchronous call through the logging system or some communication channel outside of DQCsim's control.

This function silently returns immediately if no asynchronous data was pending or if the simulator is waiting for something that has not been sent yet.

dqcs_tcfg_init_cmd()

Appends an ArbCmd to the list of initialization commands of a plugin thread.

dqcs_return_t dqcs_tcfg_init_cmd(
    dqcs_handle_t tcfg,
    dqcs_handle_t cmd
)

The ArbCmd handle is consumed by this function, and is thus invalidated, if and only if it is successful.

dqcs_tcfg_name()

Returns the configured name for the given plugin thread.

char *dqcs_tcfg_name(dqcs_handle_t tcfg)

On success, this returns a newly allocated string containing the name. Free it with free() when you're done with it to avoid memory leaks. On failure (i.e., the handle is invalid) this returns NULL.

dqcs_tcfg_new()

Creates a new plugin thread configuration object from a plugin definition.

dqcs_handle_t dqcs_tcfg_new(
    dqcs_handle_t pdef,
    const char *name
)

The plugin definition handle is consumed by this function.

dqcs_tcfg_new_raw()

Creates a new plugin thread configuration object from a callback.

dqcs_handle_t dqcs_tcfg_new_raw(
    dqcs_plugin_type_t plugin_type,
    const char *name,
    void (*callback)(
        void *user_data,
        const char *simulator
    ),
    void (*user_free)(void *user_data),
    void *user_data
)

The callback is called by DQCsim from a dedicated thread when DQCsim wants to start the plugin. The callback must then in some way spawn a plugin process that connects to the provided simulator string. The callback should return only when the process terminates.

dqcs_tcfg_tee()

Configures a plugin thread to also output its log messages to a file.

dqcs_return_t dqcs_tcfg_tee(
    dqcs_handle_t tcfg,
    dqcs_loglevel_t verbosity,
    const char *filename
)

verbosity configures the verbosity level for the file only.

dqcs_tcfg_type()

Returns the type of the given plugin thread configuration.

dqcs_plugin_type_t dqcs_tcfg_type(dqcs_handle_t tcfg)
dqcs_tcfg_verbosity_get()

Returns the configured verbosity for the given plugin thread.

dqcs_loglevel_t dqcs_tcfg_verbosity_get(dqcs_handle_t tcfg)
dqcs_tcfg_verbosity_set()

Configures the logging verbosity for the given plugin thread.

dqcs_return_t dqcs_tcfg_verbosity_set(
    dqcs_handle_t tcfg,
    dqcs_loglevel_t level
)