mirror of https://github.com/Qiskit/qiskit.git
910 lines
27 KiB
C
910 lines
27 KiB
C
// This code is part of Qiskit.
|
|
//
|
|
// (C) Copyright IBM 2025.
|
|
//
|
|
// This code is licensed under the Apache License, Version 2.0. You may
|
|
// obtain a copy of this license in the LICENSE.txt file in the root directory
|
|
// of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
|
|
//
|
|
// Any modifications or derivative works of this code must retain this
|
|
// copyright notice, and modified files need to carry a notice indicating
|
|
// that they have been altered from the originals.
|
|
|
|
#include "common.h"
|
|
#include <complex.h>
|
|
#include <qiskit.h>
|
|
#include <stdbool.h>
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
/**
|
|
* Test the zero constructor.
|
|
*/
|
|
int test_empty(void) {
|
|
QkCircuit *qc = qk_circuit_new(0, 0);
|
|
uint32_t num_qubits = qk_circuit_num_qubits(qc);
|
|
uint32_t num_clbits = qk_circuit_num_clbits(qc);
|
|
size_t num_instructions = qk_circuit_num_instructions(qc);
|
|
qk_circuit_free(qc);
|
|
|
|
if (num_qubits != 0) {
|
|
printf("The number of qubits %d is not 0", num_qubits);
|
|
return EqualityError;
|
|
}
|
|
if (num_clbits != 0) {
|
|
printf("The number of clbits %d is not 0", num_clbits);
|
|
return EqualityError;
|
|
}
|
|
if (num_instructions != 0) {
|
|
printf("The number of instructions %zu is not 0", num_instructions);
|
|
return EqualityError;
|
|
}
|
|
return Ok;
|
|
}
|
|
|
|
int test_circuit_with_quantum_reg(void) {
|
|
QkCircuit *qc = qk_circuit_new(0, 0);
|
|
QkQuantumRegister *qr = qk_quantum_register_new(1024, "my_little_register");
|
|
qk_circuit_add_quantum_register(qc, qr);
|
|
uint32_t num_qubits = qk_circuit_num_qubits(qc);
|
|
uint32_t num_clbits = qk_circuit_num_clbits(qc);
|
|
size_t num_instructions = qk_circuit_num_instructions(qc);
|
|
qk_circuit_free(qc);
|
|
qk_quantum_register_free(qr);
|
|
if (num_qubits != 1024) {
|
|
printf("The number of qubits %d is not 1024", num_qubits);
|
|
return EqualityError;
|
|
}
|
|
if (num_clbits != 0) {
|
|
printf("The number of clbits %d is not 0", num_clbits);
|
|
return EqualityError;
|
|
}
|
|
if (num_instructions != 0) {
|
|
printf("The number of instructions %zu is not 0", num_instructions);
|
|
return EqualityError;
|
|
}
|
|
return Ok;
|
|
}
|
|
|
|
int test_circuit_copy(void) {
|
|
QkCircuit *qc = qk_circuit_new(10, 10);
|
|
QkCircuit *copy = qk_circuit_copy(qc);
|
|
for (int i = 0; i < 10; i++) {
|
|
qk_circuit_measure(qc, i, i);
|
|
uint32_t qubits[1] = {
|
|
i,
|
|
};
|
|
if (i % 2 == 0) {
|
|
qk_circuit_gate(copy, QkGate_H, qubits, NULL);
|
|
}
|
|
}
|
|
size_t num_instructions = qk_circuit_num_instructions(qc);
|
|
size_t num_copy_instructions = qk_circuit_num_instructions(copy);
|
|
qk_circuit_free(qc);
|
|
qk_circuit_free(copy);
|
|
if (num_instructions == num_copy_instructions) {
|
|
printf("The number of instructions %zu is equal to the copied %zu", num_instructions,
|
|
num_copy_instructions);
|
|
return EqualityError;
|
|
}
|
|
return Ok;
|
|
}
|
|
|
|
int test_circuit_with_classical_reg(void) {
|
|
QkCircuit *qc = qk_circuit_new(0, 0);
|
|
QkClassicalRegister *cr = qk_classical_register_new(2048, "my_less_little_register");
|
|
qk_circuit_add_classical_register(qc, cr);
|
|
uint32_t num_qubits = qk_circuit_num_qubits(qc);
|
|
uint32_t num_clbits = qk_circuit_num_clbits(qc);
|
|
size_t num_instructions = qk_circuit_num_instructions(qc);
|
|
qk_circuit_free(qc);
|
|
qk_classical_register_free(cr);
|
|
if (num_qubits != 0) {
|
|
printf("The number of qubits %d is not 0", num_qubits);
|
|
return EqualityError;
|
|
}
|
|
if (num_clbits != 2048) {
|
|
printf("The number of clbits %d is not 2048", num_clbits);
|
|
return EqualityError;
|
|
}
|
|
if (num_instructions != 0) {
|
|
printf("The number of instructions %zu is not 0", num_instructions);
|
|
return EqualityError;
|
|
}
|
|
return Ok;
|
|
}
|
|
|
|
int test_circuit_copy_with_instructions(void) {
|
|
QkCircuit *qc = qk_circuit_new(10, 10);
|
|
for (int i = 0; i < 10; i++) {
|
|
qk_circuit_measure(qc, i, i);
|
|
uint32_t qubits[1] = {
|
|
i,
|
|
};
|
|
qk_circuit_gate(qc, QkGate_H, qubits, NULL);
|
|
}
|
|
QkCircuit *copy = qk_circuit_copy(qc);
|
|
size_t num_instructions = qk_circuit_num_instructions(qc);
|
|
size_t num_copy_instructions = qk_circuit_num_instructions(copy);
|
|
if (num_instructions != num_copy_instructions) {
|
|
printf("The number of instructions %zu does not equal the copied %zu", num_instructions,
|
|
num_copy_instructions);
|
|
return EqualityError;
|
|
}
|
|
|
|
for (int i = 0; i < 10; i++) {
|
|
qk_circuit_measure(qc, i, i);
|
|
uint32_t qubits[1] = {
|
|
i,
|
|
};
|
|
qk_circuit_gate(qc, QkGate_Z, qubits, NULL);
|
|
}
|
|
for (int i = 0; i < 15; i++) {
|
|
qk_circuit_measure(qc, i, i);
|
|
uint32_t qubits[1] = {
|
|
i,
|
|
};
|
|
qk_circuit_gate(copy, QkGate_X, qubits, NULL);
|
|
}
|
|
|
|
num_instructions = qk_circuit_num_instructions(qc);
|
|
num_copy_instructions = qk_circuit_num_instructions(copy);
|
|
qk_circuit_free(qc);
|
|
qk_circuit_free(copy);
|
|
if (num_instructions == num_copy_instructions) {
|
|
printf("The number of instructions %zu is equal to the copied %zu", num_instructions,
|
|
num_copy_instructions);
|
|
return EqualityError;
|
|
}
|
|
return Ok;
|
|
}
|
|
|
|
int test_no_gate_1000_bits(void) {
|
|
QkCircuit *qc = qk_circuit_new(1000, 1000);
|
|
uint32_t num_qubits = qk_circuit_num_qubits(qc);
|
|
uint32_t num_clbits = qk_circuit_num_clbits(qc);
|
|
size_t num_instructions = qk_circuit_num_instructions(qc);
|
|
qk_circuit_free(qc);
|
|
|
|
if (num_qubits != 1000) {
|
|
printf("The number of qubits %d is not 1000", num_qubits);
|
|
return EqualityError;
|
|
}
|
|
if (num_clbits != 1000) {
|
|
printf("The number of clbits %d is not 1000", num_clbits);
|
|
return EqualityError;
|
|
}
|
|
if (num_instructions != 0) {
|
|
printf("The number of instructions %zu is not 0", num_instructions);
|
|
return EqualityError;
|
|
}
|
|
|
|
return Ok;
|
|
}
|
|
|
|
int test_gate_num_qubits(void) {
|
|
for (uint8_t i = 0; i < 52; i++) {
|
|
if (i == 0) {
|
|
if (qk_gate_num_qubits(i) != 0) {
|
|
|
|
return EqualityError;
|
|
}
|
|
} else if (i < 21) {
|
|
if (qk_gate_num_qubits(i) != 1) {
|
|
return EqualityError;
|
|
}
|
|
} else if (i <= 44) {
|
|
if (qk_gate_num_qubits(i) != 2) {
|
|
return EqualityError;
|
|
}
|
|
} else if (i <= 48) {
|
|
if (qk_gate_num_qubits(i) != 3) {
|
|
return EqualityError;
|
|
}
|
|
} else {
|
|
if (qk_gate_num_qubits(i) != 4) {
|
|
return EqualityError;
|
|
}
|
|
}
|
|
}
|
|
return Ok;
|
|
}
|
|
|
|
bool value_in_array(uint8_t val, uint8_t *arr, size_t n) {
|
|
for (size_t i = 0; i < n; i++) {
|
|
if (arr[i] == val)
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
int test_gate_num_params(void) {
|
|
|
|
uint8_t zero_param_gates[29] = {1, 2, 3, 4, 5, 11, 12, 13, 14, 15, 16, 21, 22, 23, 24,
|
|
25, 26, 27, 28, 33, 34, 35, 45, 46, 47, 48, 49, 50, 51};
|
|
uint8_t one_param_gates[15] = {0, 6, 8, 9, 10, 18, 29, 30, 31, 32, 37, 39, 40, 41, 42};
|
|
uint8_t two_param_gates[4] = {7, 19, 43, 44};
|
|
|
|
for (uint8_t i = 0; i < 52; i++) {
|
|
if (value_in_array(i, zero_param_gates, 29)) {
|
|
if (qk_gate_num_params(i) != 0) {
|
|
return EqualityError;
|
|
}
|
|
} else if (value_in_array(i, one_param_gates, 15)) {
|
|
if (qk_gate_num_params(i) != 1) {
|
|
return EqualityError;
|
|
}
|
|
} else if (value_in_array(i, two_param_gates, 4)) {
|
|
if (qk_gate_num_params(i) != 2) {
|
|
return EqualityError;
|
|
}
|
|
} else if (i == 36) {
|
|
// CU takes 4 parameters theta, phi, lambda, gamma
|
|
if (qk_gate_num_params(i) != 4) {
|
|
return EqualityError;
|
|
}
|
|
} else {
|
|
if (qk_gate_num_params(i) != 3) {
|
|
return EqualityError;
|
|
}
|
|
}
|
|
}
|
|
return Ok;
|
|
}
|
|
|
|
int test_get_gate_counts_bv_no_measure(void) {
|
|
QkCircuit *qc = qk_circuit_new(1000, 1000);
|
|
double *params = NULL;
|
|
uint32_t i = 0;
|
|
uint32_t qubits[1] = {999};
|
|
qk_circuit_gate(qc, QkGate_X, qubits, params);
|
|
for (i = 0; i < 1000; i++) {
|
|
uint32_t qubits[1] = {i};
|
|
qk_circuit_gate(qc, QkGate_H, qubits, params);
|
|
}
|
|
for (i = 0; i < 1000; i += 2) {
|
|
uint32_t qubits[2] = {i, 999};
|
|
qk_circuit_gate(qc, QkGate_CX, qubits, params);
|
|
}
|
|
for (i = 0; i < 999; i++) {
|
|
uint32_t qubits[1] = {i};
|
|
qk_circuit_gate(qc, QkGate_H, qubits, params);
|
|
}
|
|
QkOpCounts op_counts = qk_circuit_count_ops(qc);
|
|
int result = Ok;
|
|
if (op_counts.len != 3) {
|
|
result = EqualityError;
|
|
goto cleanup;
|
|
}
|
|
result = strcmp(op_counts.data[2].name, "x");
|
|
if (result != 0) {
|
|
goto cleanup;
|
|
}
|
|
if (op_counts.data[2].count != 1) {
|
|
result = EqualityError;
|
|
goto cleanup;
|
|
}
|
|
result = strcmp(op_counts.data[0].name, "h");
|
|
if (result != 0) {
|
|
goto cleanup;
|
|
}
|
|
if (op_counts.data[0].count != 1999) {
|
|
result = EqualityError;
|
|
goto cleanup;
|
|
}
|
|
result = strcmp(op_counts.data[1].name, "cx");
|
|
if (result != 0) {
|
|
goto cleanup;
|
|
}
|
|
if (op_counts.data[1].count != 500) {
|
|
result = EqualityError;
|
|
goto cleanup;
|
|
}
|
|
cleanup:
|
|
qk_circuit_free(qc);
|
|
qk_opcounts_free(op_counts);
|
|
return result;
|
|
}
|
|
|
|
int test_get_gate_counts_bv_measures(void) {
|
|
QkCircuit *qc = qk_circuit_new(1000, 1000);
|
|
double *params = NULL;
|
|
uint32_t i = 0;
|
|
uint32_t qubits[1] = {999};
|
|
qk_circuit_gate(qc, QkGate_X, qubits, params);
|
|
for (i = 0; i < 1000; i++) {
|
|
uint32_t qubits[1] = {i};
|
|
qk_circuit_gate(qc, QkGate_H, qubits, params);
|
|
}
|
|
for (i = 0; i < 1000; i += 2) {
|
|
uint32_t qubits[2] = {i, 999};
|
|
qk_circuit_gate(qc, QkGate_CX, qubits, params);
|
|
}
|
|
for (i = 0; i < 999; i++) {
|
|
uint32_t qubits[1] = {i};
|
|
qk_circuit_gate(qc, QkGate_H, qubits, params);
|
|
}
|
|
for (i = 0; i < 999; i++) {
|
|
qk_circuit_measure(qc, i, i);
|
|
}
|
|
QkOpCounts op_counts = qk_circuit_count_ops(qc);
|
|
int result = Ok;
|
|
if (op_counts.len != 4) {
|
|
result = EqualityError;
|
|
goto cleanup;
|
|
}
|
|
result = strcmp(op_counts.data[3].name, "x");
|
|
if (result != 0) {
|
|
goto cleanup;
|
|
}
|
|
if (op_counts.data[3].count != 1) {
|
|
result = EqualityError;
|
|
goto cleanup;
|
|
}
|
|
result = strcmp(op_counts.data[0].name, "h");
|
|
if (result != 0) {
|
|
goto cleanup;
|
|
}
|
|
if (op_counts.data[0].count != 1999) {
|
|
result = EqualityError;
|
|
goto cleanup;
|
|
}
|
|
result = strcmp(op_counts.data[2].name, "cx");
|
|
if (result != 0) {
|
|
goto cleanup;
|
|
}
|
|
if (op_counts.data[2].count != 500) {
|
|
result = EqualityError;
|
|
goto cleanup;
|
|
}
|
|
result = strcmp(op_counts.data[1].name, "measure");
|
|
if (result != 0) {
|
|
goto cleanup;
|
|
}
|
|
if (op_counts.data[1].count != 999) {
|
|
result = EqualityError;
|
|
goto cleanup;
|
|
}
|
|
cleanup:
|
|
qk_circuit_free(qc);
|
|
qk_opcounts_free(op_counts);
|
|
return result;
|
|
}
|
|
|
|
int test_get_gate_counts_bv_barrier_and_measures(void) {
|
|
QkCircuit *qc = qk_circuit_new(1000, 1000);
|
|
double *params = NULL;
|
|
uint32_t i = 0;
|
|
uint32_t qubits[1] = {999};
|
|
qk_circuit_gate(qc, QkGate_X, qubits, params);
|
|
for (i = 0; i < 1000; i++) {
|
|
uint32_t qubits[1] = {i};
|
|
qk_circuit_gate(qc, QkGate_H, qubits, params);
|
|
}
|
|
uint32_t barrier_qubits[1000];
|
|
for (i = 0; i < 1000; i++) {
|
|
barrier_qubits[i] = i;
|
|
}
|
|
qk_circuit_barrier(qc, barrier_qubits, 1000);
|
|
for (i = 0; i < 1000; i += 2) {
|
|
uint32_t qubits[2] = {i, 999};
|
|
qk_circuit_gate(qc, QkGate_CX, qubits, params);
|
|
}
|
|
qk_circuit_barrier(qc, barrier_qubits, 1000);
|
|
for (i = 0; i < 999; i++) {
|
|
uint32_t qubits[1] = {i};
|
|
qk_circuit_gate(qc, QkGate_H, qubits, params);
|
|
}
|
|
for (i = 0; i < 999; i++) {
|
|
qk_circuit_measure(qc, i, i);
|
|
}
|
|
QkOpCounts op_counts = qk_circuit_count_ops(qc);
|
|
int result = Ok;
|
|
if (op_counts.len != 5) {
|
|
result = EqualityError;
|
|
goto cleanup;
|
|
}
|
|
result = strcmp(op_counts.data[4].name, "x");
|
|
if (result != 0) {
|
|
goto cleanup;
|
|
}
|
|
if (op_counts.data[4].count != 1) {
|
|
result = EqualityError;
|
|
goto cleanup;
|
|
}
|
|
result = strcmp(op_counts.data[0].name, "h");
|
|
if (result != 0) {
|
|
goto cleanup;
|
|
}
|
|
if (op_counts.data[0].count != 1999) {
|
|
result = EqualityError;
|
|
goto cleanup;
|
|
}
|
|
result = strcmp(op_counts.data[2].name, "cx");
|
|
if (result != 0) {
|
|
goto cleanup;
|
|
}
|
|
if (op_counts.data[2].count != 500) {
|
|
result = EqualityError;
|
|
goto cleanup;
|
|
}
|
|
result = strcmp(op_counts.data[1].name, "measure");
|
|
if (result != 0) {
|
|
return result;
|
|
}
|
|
if (op_counts.data[1].count != 999) {
|
|
result = EqualityError;
|
|
goto cleanup;
|
|
}
|
|
result = strcmp(op_counts.data[3].name, "barrier");
|
|
if (result != 0) {
|
|
goto cleanup;
|
|
}
|
|
if (op_counts.data[3].count != 2) {
|
|
return EqualityError;
|
|
result = EqualityError;
|
|
goto cleanup;
|
|
}
|
|
cleanup:
|
|
qk_circuit_free(qc);
|
|
qk_opcounts_free(op_counts);
|
|
return result;
|
|
}
|
|
|
|
int test_get_gate_counts_bv_resets_barrier_and_measures(void) {
|
|
QkCircuit *qc = qk_circuit_new(1000, 1000);
|
|
double *params = NULL;
|
|
uint32_t i = 0;
|
|
uint32_t qubits[1] = {999};
|
|
for (i = 0; i < 1000; i++) {
|
|
qk_circuit_reset(qc, i);
|
|
}
|
|
qk_circuit_gate(qc, QkGate_X, qubits, params);
|
|
for (i = 0; i < 1000; i++) {
|
|
uint32_t qubits[1] = {i};
|
|
qk_circuit_gate(qc, QkGate_H, qubits, params);
|
|
}
|
|
uint32_t barrier_qubits[1000];
|
|
for (i = 0; i < 1000; i++) {
|
|
barrier_qubits[i] = i;
|
|
}
|
|
qk_circuit_barrier(qc, barrier_qubits, 1000);
|
|
for (i = 0; i < 1000; i += 2) {
|
|
uint32_t qubits[2] = {i, 999};
|
|
qk_circuit_gate(qc, QkGate_CX, qubits, params);
|
|
}
|
|
qk_circuit_barrier(qc, barrier_qubits, 1000);
|
|
for (i = 0; i < 999; i++) {
|
|
uint32_t qubits[1] = {i};
|
|
qk_circuit_gate(qc, QkGate_H, qubits, params);
|
|
}
|
|
for (i = 0; i < 999; i++) {
|
|
qk_circuit_measure(qc, i, i);
|
|
}
|
|
QkOpCounts op_counts = qk_circuit_count_ops(qc);
|
|
int result = Ok;
|
|
if (op_counts.len != 6) {
|
|
result = EqualityError;
|
|
goto cleanup;
|
|
}
|
|
result = strcmp(op_counts.data[5].name, "x");
|
|
if (result != 0) {
|
|
goto cleanup;
|
|
}
|
|
if (op_counts.data[5].count != 1) {
|
|
result = EqualityError;
|
|
goto cleanup;
|
|
}
|
|
result = strcmp(op_counts.data[0].name, "h");
|
|
if (result != 0) {
|
|
goto cleanup;
|
|
}
|
|
if (op_counts.data[0].count != 1999) {
|
|
result = EqualityError;
|
|
goto cleanup;
|
|
}
|
|
result = strcmp(op_counts.data[3].name, "cx");
|
|
if (result != 0) {
|
|
goto cleanup;
|
|
}
|
|
if (op_counts.data[3].count != 500) {
|
|
result = EqualityError;
|
|
goto cleanup;
|
|
}
|
|
result = strcmp(op_counts.data[2].name, "measure");
|
|
if (result != 0) {
|
|
goto cleanup;
|
|
}
|
|
if (op_counts.data[2].count != 999) {
|
|
result = EqualityError;
|
|
goto cleanup;
|
|
}
|
|
result = strcmp(op_counts.data[4].name, "barrier");
|
|
if (result != 0) {
|
|
goto cleanup;
|
|
}
|
|
if (op_counts.data[4].count != 2) {
|
|
result = EqualityError;
|
|
goto cleanup;
|
|
}
|
|
result = strcmp(op_counts.data[1].name, "reset");
|
|
if (result != 0) {
|
|
goto cleanup;
|
|
}
|
|
if (op_counts.data[1].count != 1000) {
|
|
result = EqualityError;
|
|
goto cleanup;
|
|
}
|
|
size_t num_instructions = qk_circuit_num_instructions(qc);
|
|
if (num_instructions != 1000 + 2 + 999 + 500 + 1999 + 1) {
|
|
result = EqualityError;
|
|
goto cleanup;
|
|
}
|
|
QkCircuitInstruction *inst = malloc(sizeof(QkCircuitInstruction));
|
|
for (size_t i = 0; i < num_instructions; i++) {
|
|
|
|
qk_circuit_get_instruction(qc, i, inst);
|
|
if (i < 1000) {
|
|
result = strcmp(inst->name, "reset");
|
|
if (result != 0) {
|
|
goto loop_exit;
|
|
}
|
|
if (inst->qubits[0] != i || inst->num_qubits != 1) {
|
|
result = EqualityError;
|
|
goto loop_exit;
|
|
}
|
|
if (inst->num_clbits > 0 || inst->num_params > 0) {
|
|
result = EqualityError;
|
|
goto loop_exit;
|
|
}
|
|
} else if (i == 1000) {
|
|
result = strcmp(inst->name, "x");
|
|
if (result != 0) {
|
|
goto loop_exit;
|
|
}
|
|
if (inst->qubits[0] != 999 || inst->num_qubits != 1) {
|
|
result = EqualityError;
|
|
goto loop_exit;
|
|
}
|
|
if (inst->num_clbits > 0 || inst->num_params > 0) {
|
|
result = EqualityError;
|
|
goto loop_exit;
|
|
}
|
|
} else if (i < 2001) {
|
|
result = strcmp(inst->name, "h");
|
|
if (result != 0) {
|
|
goto loop_exit;
|
|
}
|
|
if (inst->qubits[0] != i - 1001 || inst->num_qubits != 1) {
|
|
result = EqualityError;
|
|
goto loop_exit;
|
|
}
|
|
if (inst->num_clbits > 0 || inst->num_params > 0 || inst->num_qubits != 1) {
|
|
result = EqualityError;
|
|
goto loop_exit;
|
|
}
|
|
} else if (i == 2001) {
|
|
result = strcmp(inst->name, "barrier");
|
|
if (result != 0) {
|
|
goto loop_exit;
|
|
}
|
|
for (uint32_t j = 0; i < 1000; j++) {
|
|
if (inst->qubits[i] != i) {
|
|
result = EqualityError;
|
|
goto loop_exit;
|
|
}
|
|
}
|
|
if (inst->num_clbits > 0 || inst->num_params > 0 || inst->num_qubits != 1000) {
|
|
result = EqualityError;
|
|
goto loop_exit;
|
|
}
|
|
} else if (i <= 2501) {
|
|
result = strcmp(inst->name, "cx");
|
|
if (result != 0) {
|
|
goto loop_exit;
|
|
}
|
|
if (inst->qubits[0] != (i - 2002) * 2) {
|
|
result = EqualityError;
|
|
goto loop_exit;
|
|
}
|
|
if (inst->qubits[1] != 999 || inst->num_qubits != 2) {
|
|
result = EqualityError;
|
|
goto loop_exit;
|
|
}
|
|
if (inst->num_clbits > 0 || inst->num_params > 0) {
|
|
result = EqualityError;
|
|
goto loop_exit;
|
|
}
|
|
} else if (i == 2502) {
|
|
result = strcmp(inst->name, "barrier");
|
|
if (result != 0) {
|
|
goto loop_exit;
|
|
}
|
|
for (uint32_t j = 0; i < 1000; j++) {
|
|
if (inst->qubits[i] != i) {
|
|
result = EqualityError;
|
|
goto loop_exit;
|
|
}
|
|
}
|
|
if (inst->num_clbits > 0 || inst->num_params > 0 || inst->num_qubits != 1000) {
|
|
result = EqualityError;
|
|
goto loop_exit;
|
|
}
|
|
} else if (i <= 3501) {
|
|
result = strcmp(inst->name, "h");
|
|
if (result != 0) {
|
|
goto loop_exit;
|
|
}
|
|
if (inst->qubits[0] != i - 2503 || inst->num_qubits != 1) {
|
|
result = EqualityError;
|
|
goto loop_exit;
|
|
}
|
|
if (inst->num_clbits > 0 || inst->num_params > 0) {
|
|
result = EqualityError;
|
|
goto loop_exit;
|
|
}
|
|
} else if (i <= 4500) {
|
|
result = strcmp(inst->name, "measure");
|
|
if (result != 0) {
|
|
goto loop_exit;
|
|
}
|
|
if (inst->qubits[0] != i - 3502 || inst->num_qubits != 1) {
|
|
result = EqualityError;
|
|
goto loop_exit;
|
|
}
|
|
if (inst->clbits[0] != i - 3502 || inst->num_clbits != 1) {
|
|
result = EqualityError;
|
|
goto loop_exit;
|
|
}
|
|
if (inst->num_params > 0) {
|
|
result = EqualityError;
|
|
goto loop_exit;
|
|
}
|
|
}
|
|
loop_exit:
|
|
qk_circuit_instruction_clear(inst);
|
|
if (result != 0) {
|
|
break;
|
|
}
|
|
}
|
|
cleanup:
|
|
free(inst);
|
|
qk_circuit_free(qc);
|
|
qk_opcounts_free(op_counts);
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Test appending a unitary gate.
|
|
*/
|
|
int test_unitary_gate(void) {
|
|
QkCircuit *qc = qk_circuit_new(2, 0);
|
|
uint32_t qubits[2] = {0, 1};
|
|
|
|
QkComplex64 c0 = {0.0, 0.0};
|
|
QkComplex64 c1 = {1.0, 0.0};
|
|
QkComplex64 matrix[16] = {c1, c0, c0, c0, // this
|
|
c0, c1, c0, c0, // is
|
|
c0, c0, c1, c0, // for
|
|
c0, c0, c0, c1}; // formatting
|
|
|
|
int ec = qk_circuit_unitary(qc, matrix, qubits, 2, false);
|
|
if (ec != QkExitCode_Success) {
|
|
qk_circuit_free(qc);
|
|
return ec;
|
|
}
|
|
|
|
int result = Ok;
|
|
|
|
size_t num_inst = qk_circuit_num_instructions(qc);
|
|
if (num_inst != 1) {
|
|
result = EqualityError;
|
|
goto cleanup;
|
|
}
|
|
|
|
QkOpCounts op_counts = qk_circuit_count_ops(qc);
|
|
if (op_counts.len != 1 || strcmp(op_counts.data[0].name, "unitary") != 0 ||
|
|
op_counts.data[0].count != 1) {
|
|
result = EqualityError;
|
|
qk_opcounts_free(op_counts);
|
|
goto cleanup;
|
|
}
|
|
qk_opcounts_free(op_counts);
|
|
|
|
QkCircuitInstruction *inst = malloc(sizeof(QkCircuitInstruction));
|
|
qk_circuit_get_instruction(qc, 0, inst);
|
|
if (strcmp(inst->name, "unitary") != 0 || inst->num_clbits != 0 || inst->num_params != 0 ||
|
|
inst->num_qubits != 2) {
|
|
result = EqualityError;
|
|
}
|
|
qk_circuit_instruction_clear(inst);
|
|
free(inst);
|
|
|
|
cleanup:
|
|
qk_circuit_free(qc);
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Test appending a unitary gate.
|
|
*/
|
|
int test_unitary_gate_1q(void) {
|
|
QkCircuit *qc = qk_circuit_new(2, 0);
|
|
uint32_t qubits[1] = {0};
|
|
|
|
QkComplex64 c0 = {0.0, 0.0};
|
|
QkComplex64 c1 = {1.0, 0.0};
|
|
QkComplex64 matrix[4] = {c1, c0, // this
|
|
c0, c1}; // is
|
|
|
|
int ec = qk_circuit_unitary(qc, matrix, qubits, 1, false);
|
|
if (ec != QkExitCode_Success) {
|
|
qk_circuit_free(qc);
|
|
return ec;
|
|
}
|
|
|
|
int result = Ok;
|
|
|
|
size_t num_inst = qk_circuit_num_instructions(qc);
|
|
if (num_inst != 1) {
|
|
result = EqualityError;
|
|
goto cleanup;
|
|
}
|
|
|
|
QkOpCounts op_counts = qk_circuit_count_ops(qc);
|
|
if (op_counts.len != 1 || strcmp(op_counts.data[0].name, "unitary") != 0 ||
|
|
op_counts.data[0].count != 1) {
|
|
result = EqualityError;
|
|
qk_opcounts_free(op_counts);
|
|
goto cleanup;
|
|
}
|
|
qk_opcounts_free(op_counts);
|
|
|
|
QkCircuitInstruction *inst = malloc(sizeof(QkCircuitInstruction));
|
|
qk_circuit_get_instruction(qc, 0, inst);
|
|
if (strcmp(inst->name, "unitary") != 0 || inst->num_clbits != 0 || inst->num_params != 0 ||
|
|
inst->num_qubits != 1) {
|
|
result = EqualityError;
|
|
}
|
|
qk_circuit_instruction_clear(inst);
|
|
free(inst);
|
|
|
|
cleanup:
|
|
qk_circuit_free(qc);
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Test appending a unitary gate.
|
|
*/
|
|
int test_unitary_gate_3q(void) {
|
|
QkCircuit *qc = qk_circuit_new(3, 0);
|
|
uint32_t qubits[3] = {0, 1, 2};
|
|
|
|
QkComplex64 c0 = {0.0, 0.0};
|
|
QkComplex64 c1 = {1.0, 0.0};
|
|
QkComplex64 matrix[64] = {c1, c0, c0, c0, c0, c0, c0, c0, // this
|
|
c0, c1, c0, c0, c0, c0, c0, c0, // is
|
|
c0, c0, c1, c0, c0, c0, c0, c0, // for
|
|
c0, c0, c0, c1, c0, c0, c0, c0, // formatting
|
|
c0, c0, c0, c0, c1, c0, c0, c0, // this
|
|
c0, c0, c0, c0, c0, c1, c0, c0, // to
|
|
c0, c0, c0, c0, c0, c0, c1, c0, // look
|
|
c0, c0, c0, c0, c0, c0, c0, c1}; // like a matrix
|
|
|
|
int ec = qk_circuit_unitary(qc, matrix, qubits, 3, false);
|
|
if (ec != QkExitCode_Success) {
|
|
qk_circuit_free(qc);
|
|
return ec;
|
|
}
|
|
|
|
int result = Ok;
|
|
|
|
size_t num_inst = qk_circuit_num_instructions(qc);
|
|
if (num_inst != 1) {
|
|
result = EqualityError;
|
|
goto cleanup;
|
|
}
|
|
|
|
QkOpCounts op_counts = qk_circuit_count_ops(qc);
|
|
if (op_counts.len != 1 || strcmp(op_counts.data[0].name, "unitary") != 0 ||
|
|
op_counts.data[0].count != 1) {
|
|
result = EqualityError;
|
|
qk_opcounts_free(op_counts);
|
|
goto cleanup;
|
|
}
|
|
qk_opcounts_free(op_counts);
|
|
QkCircuitInstruction *inst = malloc(sizeof(QkCircuitInstruction));
|
|
qk_circuit_get_instruction(qc, 0, inst);
|
|
if (strcmp(inst->name, "unitary") != 0 || inst->num_clbits != 0 || inst->num_params != 0 ||
|
|
inst->num_qubits != 3) {
|
|
result = EqualityError;
|
|
}
|
|
qk_circuit_instruction_clear(inst);
|
|
free(inst);
|
|
|
|
cleanup:
|
|
qk_circuit_free(qc);
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Test passing a non-unitary gate returns the correct exit code.
|
|
*/
|
|
int test_not_unitary_gate(void) {
|
|
QkCircuit *qc = qk_circuit_new(2, 0);
|
|
uint32_t qubits[2] = {0, 1};
|
|
|
|
QkComplex64 c0 = {0.0, 0.0};
|
|
QkComplex64 c1 = {1.0, 0.0};
|
|
QkComplex64 matrix[16] = {c1, c1, c0, c0, // this
|
|
c1, c1, c0, c0, // is
|
|
c0, c0, c1, c0, // for
|
|
c0, c0, c0, c1}; // formatting
|
|
|
|
int exit_code = qk_circuit_unitary(qc, matrix, qubits, 2, true);
|
|
|
|
int result = Ok;
|
|
if (exit_code != QkExitCode_ExpectedUnitary) {
|
|
printf("Got exit code %i but expected %i", exit_code, QkExitCode_ExpectedUnitary);
|
|
result = EqualityError;
|
|
goto cleanup;
|
|
}
|
|
|
|
size_t num_inst = qk_circuit_num_instructions(qc);
|
|
if (num_inst != 0) { // we expect no gate was added
|
|
printf("Found gate when none should be added");
|
|
result = EqualityError;
|
|
goto cleanup;
|
|
}
|
|
|
|
cleanup:
|
|
qk_circuit_free(qc);
|
|
return result;
|
|
}
|
|
|
|
int test_delay_instruction(void) {
|
|
QkCircuit *qc = qk_circuit_new(2, 0);
|
|
int result = Ok;
|
|
|
|
QkExitCode delay_s_code;
|
|
|
|
delay_s_code = qk_circuit_delay(qc, 0, 0.001, QkDelayUnit_S);
|
|
if (delay_s_code != QkExitCode_Success) {
|
|
result = RuntimeError;
|
|
goto cleanup;
|
|
}
|
|
|
|
cleanup:
|
|
qk_circuit_free(qc);
|
|
return result;
|
|
}
|
|
|
|
int test_circuit(void) {
|
|
int num_failed = 0;
|
|
num_failed += RUN_TEST(test_empty);
|
|
num_failed += RUN_TEST(test_circuit_with_quantum_reg);
|
|
num_failed += RUN_TEST(test_circuit_with_classical_reg);
|
|
num_failed += RUN_TEST(test_circuit_copy);
|
|
num_failed += RUN_TEST(test_circuit_copy_with_instructions);
|
|
num_failed += RUN_TEST(test_no_gate_1000_bits);
|
|
num_failed += RUN_TEST(test_get_gate_counts_bv_no_measure);
|
|
num_failed += RUN_TEST(test_get_gate_counts_bv_measures);
|
|
num_failed += RUN_TEST(test_get_gate_counts_bv_barrier_and_measures);
|
|
num_failed += RUN_TEST(test_get_gate_counts_bv_resets_barrier_and_measures);
|
|
num_failed += RUN_TEST(test_gate_num_qubits);
|
|
num_failed += RUN_TEST(test_gate_num_params);
|
|
num_failed += RUN_TEST(test_delay_instruction);
|
|
num_failed += RUN_TEST(test_unitary_gate);
|
|
num_failed += RUN_TEST(test_not_unitary_gate);
|
|
num_failed += RUN_TEST(test_unitary_gate_1q);
|
|
num_failed += RUN_TEST(test_unitary_gate_3q);
|
|
|
|
fflush(stderr);
|
|
fprintf(stderr, "=== Number of failed subtests: %i\n", num_failed);
|
|
|
|
return num_failed;
|
|
}
|