CQC C LibraryΒΆ

The library is defined in cqc.h and implemented in cqc.c.

All the CQC headers are defined as __packed__ structs in cqc.h.

CQC connection state is kept in the following structure:

typedef struct
{
    int sockfd;       // connection to CQC backend
    uint16_t app_id;  // application ID
} cqc_ctx;

All CQC library function return an int that takes one of the following values:

enum cqc_lib_rc
{
    CQC_LIB_OK = 0,
    CQC_LIB_ERR = -1,
};

The EPR commands also return an entanglement header:

typedef struct
{
    uint32_t node_A;            /* IP of this node */
    uint16_t port_A;            /* Port of this node */
    uint16_t app_id_A;          /* App ID of this node */
    uint32_t node_B;            /* IP of other node */
    uint16_t port_B;            /* Port of other node */
    uint16_t app_id_B;          /* App ID of other node */
    uint32_t id_AB;             /* Entanglement identifier */
    uint64_t timestamp;         /* Creation time */
    uint64_t tog;               /* Time of goodness */
    uint16_t goodness;          /* Goodness parameter */
    uint8_t df;                 /* Directionality flag creation */
    uint8_t unused;             /* Not used - align */
} __attribute__((__packed__)) entanglementHeader;

The following functions are available in the library. To execute a specific command, you need to use the right message type as defined in cqc.h. These can also be found in this documentation https://softwarequtech.github.io/CQC-Python/interface.html:

/*
 * cqc_init
 *
 * Create and return a cqc_ctx handle.
 *
 * Arguments:
 * app_id    ID to use for this application
 */
cqc_ctx *cqc_init(uint16_t app_id)

/*
 * cqc_connect
 *
 * Connect to CQC backend.
 *
 * Arguments:
 *
 * hostname    hostname of the CQC backend
 * portno      port of the CQC backend
 */
int cqc_connect(cqc_ctx *cqc, char *hostname, int portno)

/*
 * cqc_close
 *
 * Disconnect from the backend.
 */
void cqc_close(cqc_ctx *cqc)

/*
 * cqc_destroy
 *
 * Free the resources allocated for this cqc_ctx handle (including itself).
 */
void cqc_destroy(cqc_ctx *cqc)

/*
 * send_cqc_header
 *
 * Prepare and send the top-level CQC header.
 *
 * Arguments:
 * type    the message type
 * len     length of subsequent headers
 */
int send_cqc_header(cqc_ctx *cqc, uint8_t type, uint32_t len)

/*
 * send_cqc_cmd
 *
 * Build and send the CQC header and the command header.
 *
 * Arguments:
 * command     command identifier to be sent
 * qubit_id    identifier of qubit on which to perform this command
 * notify      whether to request a DONE upon completion
 * action      set if there are more actions to execute when done
 * block       block other instructions until this command is done
 * length      length of any headers that are to follow
 */
int send_cqc_cmd(cqc_ctx *cqc,
                 uint8_t command,
                 uint16_t qubit_id,
                 bool notify,
                 bool action,
                 bool block,
                 uint32_t length)

/*
 * cqc_hello
 *
 * Sends a HELLO message to the CQC backend.
 */
int cqc_hello(cqc_ctx *cqc)

/*
 * cqc_simple_cmd
 *
 * Executes a simple CQC command (not requiring any additional details).
 *
 * Arguments:
 * command     command identifier to be sent
 * qubit_id    identifier of qubit on which to perform this command
 * notify      whether to request a DONE upon completion
 */
int cqc_simple_cmd(cqc_ctx *cqc,
                   uint8_t command,
                   uint16_t qubit_id,
                   bool notify)

/*
 * cqc_send
 *
 * Send a qubit to a remote node.
 *
 * Arguments:
 * qubit_id         qubit to send
 * remote_app_id    app id on the remote node to send to
 * remote_node      address of remote node (IPv4)
 * remote_port      port for classical control info
 */
int cqc_send(cqc_ctx *cqc,
             uint16_t qubit_id,
             uint16_t remote_app_id,
             uint16_t remote_port,
             uint32_t remote_node)

/*
 * cqc_recv
 *
 * Receive a qubit.
 *
 * Arguments:
 * qubit_id    (OUT) ID assigned to the received qubit
 */
int cqc_recv(cqc_ctx *cqc, uint16_t *qubit_id)

/*
 * cqc_measure
 *
 * Measure a specific qubit. This will block until the reply is received.
 *
 * Arguments:
 * qubit_id    qubit to measure
 * meas_out    (OUT) measurement outcome
 */
int cqc_measure(cqc_ctx *cqc, uint16_t qubit_id, uint8_t *meas_out)

/*
 * cqc_wait_until_done
 *
 * Receive certain number of DONE commands before proceeding.
 *
 * Arguments:
 * reps    number of replies to wait for
 */
int cqc_wait_until_done(cqc_ctx *cqc, unsigned int reps)

/*
 * cqc_wait_until_newok
 *
 * Wait until qubit creation is confirmed.
 *
 * Arguments:
 * qubit_id    (OUT) ID of created qubit
 */
int cqc_wait_until_newok(cqc_ctx *cqc, uint16_t *qubit_id)

/*
 *  cqc_twoqubit
 *
 *  Execute local two qubit gate.
 *
 *  Arguments:
 *  command    command id to execute
 *  qubit1     number of the first qubit
 *  qubit2     number of the second qubit
 */
int cqc_twoqubit(cqc_ctx *cqc,
                 uint8_t command,
                 uint16_t qubit1,
                 uint16_t qubit2)

/*
 * cqc_epr
 *
 * Generate EPR pair with remote node.
 *
 * Arguments:
 * remote_app_id    app id on the remote node
 * remote_node      address of remote node to receive from (IPv4)
 * remote_port      port for classical control info
 * qubit_id         (OUT) ID of local qubit of the EPR pair
 * ent_info         (OUT) etanglement information
 */
int cqc_epr(cqc_ctx *cqc,
            uint16_t remote_app_id,
            uint16_t remote_port,
            uint32_t remote_node,
            uint16_t *qubit_id,
            entanglementHeader *ent_info)

/*
 * cqc_epr_recv
 *
 * Receive EPR pair.
 *
 * qubit_id         (OUT) ID of local qubit of the EPR pair
 * ent_info         (OUT) etanglement information
 */
int cqc_epr_recv(cqc_ctx *cqc,
                 uint16_t *qubit_id,
                 entanglementHeader *ent_info)