Skip to main content
IBM Quantum Platform

QkCustomOp

typedef struct QkCustomOp QkCustomOp

Una representación de una operación que se ha definido en C.

Este objeto de operación contiene la funcionalidad mínima que debe cumplir un objeto para poder actuar sobre un QkCircuit.

Cualquier objeto que se pueda implementar mediante QkCustomOp se distribuirá dinámicamente para añadirlo al circuito. En otras palabras, el circuito no sabe qué tipo de objeto está aceptando, pero funcionará con él siempre y cuando tenga la funcionalidad que se espera de cualquier operación.

Para ello, una operación se define mediante dos elementos: - El puntero original a la estructura de la operación. - El puntero a una tabla virtual (vtable) con las ranuras de función que definen la funcionalidad de dicha operación. Consulte qk_custom_op_vtable_new() para obtener más detalles.

Aquí tienes un ejemplo rápido de cómo queda:

// Define an operation with a single attribute.
struct foo_gate {
   uint32_t num_qubits;
};
// Represents the name of the operation.
const char *FOO_NAME = "foo";
// Design the required methods for the vtable.
const char *foo_name(const void *gate) {
   // Cast void to original pointer.
   struct foo_gate *_self = (struct foo_gate *)gate;
   // Cast once more to consume it
   (void)_self;
   return FOO_NAME;
}
uint32_t foo_num_qubits(const void *gate) {
   struct foo_gate *self = (struct foo_gate *)gate;
   // Used stored attirbute as return value.
   return self->num_qubits;
}
// Use same logic below for required methods that have
// fixed values.
uint32_t foo_num_clbits(const void *gate) {
   struct foo_gate *_self = (struct foo_gate *)gate;
   (void)_self;
   return 0;
}
// Implement all required methods.
// Build list of entries for the vtable (at least 7 required entries)
QkCustomOpVtableEntry entries[7] = {
   {.slot = 0, .func = foo_name},
   {.slot = 1, .func = foo_num_qubits},
   {.slot = 2, .func = foo_num_clbits},
   // ...
   // End with sentinel value
   {.slot = -1, .func = NULL},
};
// Create a vtable
QkCustomOpVtable *foo_vtable = qk_custom_op_vtable_new(entries);
// Declare a sample instance
struct foo_gate foo_3q = {
   .num_qubits = 3,
};
// Create the custom operation
QkCustomOp *foo_3q_custom = qk_custom_op_new(&foo_3q, foo_vtable);
// Add to a circuit
QkCircuit *circuit = qk_circuit_new(3, 0);
uint32_t qubits[3] = {0, 1, 2};
qk_circuit_custom_operation(circuit, foo_3q_custom, qubits, NULL, NULL);

Tipos de datos

QkCustomOpSlot

enum QkCustomOpSlot

Representa el índice de la tabla de funciones virtuales (Vtable) de un objeto QkCustomOp procedente del dominio C.

Cada índice con nombre hace referencia a un método obligatorio /opt imativo de los rasgos CustomOperation y Operation en Rust.

Valores:

enumerador QkCustomOpSlot_Name

enumerador QkCustomOpSlot_NumQubits

enumerador QkCustomOpSlot_NumClbits

enumerador QkCustomOpSlot_NumParams

enumerador QkCustomOpSlot_Directive

enumerador QkCustomOpSlot_IsUnitary

enumerador QkCustomOpSlot_NumCtrlQubits

enumerador QkCustomOpSlot_Label

enumerador QkCustomOpSlot_Definition

enumerador QkCustomOpSlot_Eq

enumerador QkCustomOpSlot_Clone

enumerador QkCustomOpSlot_Delete


Funciones

qk_custom_operation_new

QkCustomOp *qk_custom_operation_new(void *operation, const QkCustomOpVtable *v_table)

Crea un QkCustomOp basado en una operación cuántica definida íntegramente en C.

Aquí tienes un ejemplo rápido de cómo queda:

// Define an operation with a single attribute.
struct foo_gate {
    uint32_t num_qubits;
}

// Implement all required methods
uint32_t foo_num_qubits(const void *gate) {
struct foo_gate *self = (struct foo_gate *)gate;
// Used stored attirbute as return value.
return self->num_qubits;
}

// Build list of entries for the vtable (at least 7 required entries)
QkVtableEntry entries[7] = {
    {.slot = QkCustomOpSlot_NumQubits, .func = foo_num_qubits},
// ...
// End with sentinel value
    {.slot = -1, .func = NULL},
};

// Create a vtable
QkCustomOpVtable *foo_vtable = qk_custom_operation_vtable_new(entries);

// Declare a sample instance
struct foo_gate foo_3q = {
    .num_qubits = 3,
};

// Create the custom operation
QkCustomOp foo_3q_custom = qk_custom_operation_new(&foo_3q, foo_vtable);

Seguridad

Es responsabilidad de los programadores asegurarse de que los datos incluidos en la estructura operation puedan:

  • Se puede acceder a él de forma segura desde varios subprocesos simultáneamente.
  • Puede ser tomado en préstamo de forma inmutable por otros subprocesos sin provocar condiciones de carrera.
  • Se conservará durante toda la vida útil de la operación.

El comportamiento es indefinido si el v_table puntero proporcionado es nulo o no está alineado.

El incumplimiento de estas condiciones puede dar lugar a un comportamiento indefinido.

Parámetros

  • operación : un puntero propio a la estructura de la operación.
  • v_table : un puntero a una v_table correctamente construida, diseñada para funcionar con los datos a los que operation apunta la estructura.

Devuelve

Un puntero a QkCustomOp.

qk_custom_operation_free

void qk_custom_operation_free(QkCustomOp *data)

Liberar un :c:typeQkCustomOp: propio.

Normalmente no es necesario llamar a esta función, ya que :c:func:qk_circuit_custom_operation se hace cargo del objeto.

Esta función no realiza ninguna operación si se le pasa NULL.

Seguridad

El comportamiento no está definido si no data es nulo ni un puntero de propiedad válido a un :c:typeQkCustomOp:.

Parámetros

  • datos : un puntero de propiedad a los datos que se van a liberar.

qk_custom_operation_vtable_new

const QkCustomOpVtable *qk_custom_operation_vtable_new(const QkVtableEntry *slots)

Crea un QkCustomOpVtable a partir de una lista de instancias QkVtableEntry .

La tabla virtual se construye a partir de un conjunto de ranuras que contienen un índice y un puntero a una función con los tipos de argumento y de retorno correctos.

Consulta la siguiente tabla para identificar las ranuras correctas.

Ranura
Tipo de argumento(s)
Tipo de retorno
Índice
Obligatorio
Valor predeterminado
nameconst void *char *QkCustomOpSlot_NameSín/d
num_qubitsconst void *uint32_tQkCustomOpSlot_NumQubitsSín/d
num_clbitsconst void *uint32_tQkCustomOpSlot_NumClbitsNo0
num_paramsconst void *uint32_tQkCustomOpSlot_NumParamsNo0
directiveconst void *boolQkCustomOpSlot_DirectiveNofalse
is_unitaryconst void *boolQkCustomOpSlot_IsUnitaryNotrue
num_ctrl_qubitsconst void *uint32_tQkCustomOpSlot_NumCtrlQubitsNo0
labelconst void *char *QkCustomOpSlot_LabelNoNULL
definitionconst void *, QkParam **QkCircuit *QkCustomOpSlot_DefinitionNoNULL
eqconst void *, const void *boolQkCustomOpSlot_EqNoComparación de punteros
cloneconst void *void *QkCustomOpSlot_CloneNoalias de puntero
deletevoid *voidQkCustomOpSlot_DeleteNoNO-OP

Rust considerará cada función como un void puntero y la convertirá en un puntero a función con la firma correcta.

Si no se recibe un slot obligatorio, la vtable no se creará y esta función devolverá un puntero NULL . Si no se incluye una ranura opcional, la tabla virtual se creará de todos modos y sus ranuras apuntarán a las implementaciones por defecto de dichos métodos.

Si una ranura no tiene un índice válido (aparte del valor centinela), se ignorará el puntero a la función proporcionado. De este modo se garantiza que, aunque se añadan o se eliminen métodos no obligatorios del cuadro anterior, el programa siga funcionando sin problemas.

Cada lista de ranuras debe estar delimitada por un valor centinela QkVtableEntry al final. El centinela debería tener el siguiente aspecto:

QkVtableEntry sentinel = {.slot = -1, .func = NULL};

Esta función dejará de leer cualquier ranura situada después de encontrar el centinela.

Seguridad

El comportamiento es indefinido si se proporciona una lista de entradas sin un valor centinela delimitador.

También puede producirse un comportamiento indefinido durante la transmutación si el puntero a función proporcionado no tiene la firma correcta.

Parámetros

  • slots : un puntero a una lista de entradas delimitada por una entrada con un valor centinela.

Devuelve

Un puntero a una tabla de funciones virtual (vtable) construida o un puntero nulo si faltan entradas obligatorias.

qk_custom_operation_vtable_free

void qk_custom_operation_vtable_free(const QkCustomOpVtable *v_table)

Libera el puntero QkCustomOpVtable

Seguridad

Puede producirse un comportamiento indefinido si v_table es un o NULL un puntero no alineado e inválido a un QkCustomOpVtable.

Parámetros

  • v_table – El puntero a un objeto QkCustomOpVtable .
¿Le ha resultado útil esta página?
Informe de un error, de una errata o solicite contenido en GitHub.