From: miha-q <> Date: Sat, 9 Mar 2024 03:13:04 +0000 (-0500) Subject: Fri Mar 8 10:13:04 PM EST 2024 X-Git-Url: http://www.foleosoft.com/?a=commitdiff_plain;h=963065213610d164ff49e46cb25d274ca35b3bd7;p=QAnsel.git Fri Mar 8 10:13:04 PM EST 2024 --- diff --git a/Makefile b/Makefile index bcf674e..7406d5a 100644 --- a/Makefile +++ b/Makefile @@ -1,11 +1,11 @@ all: - mv src/kernel.cl src/.kernel.cl - bash -c 'echo -ne "$$(cat src/.kernel.cl)\x00" > src/kernel.cl' - xxd -i src/kernel.cl | sed -e 's/gpu_gpu_/gpu_/g' > src/kernel.cl.c - mv src/.kernel.cl src/kernel.cl - cat src/kernel.cl | grep -vi '{gpu_only}' | sed -e 's/\/\/\(.*\){cpu_only}/\1/' -e 's/__global //' -e 's/__kernel //' > src/kernel_cpu.cl.c + + cat src/kernel.cl | grep -vi '{gpu_only}' | sed -e 's/__global //' -e 's/__kernel //' > src/kernel_cpu.cl + cat src/kernel.cl | grep -vi '{cpu_only}' > src/.kernel.tmp.1 + bash -c 'echo -ne "$$(cat src/.kernel.tmp.1)\x00" > src/.kernel.tmp.2' + xxd -i src/.kernel.tmp.2 | sed -e 's/src__kernel_tmp_2/kernel_gpu/' > src/kernel_gpu.cl gcc src/QAnsel.c -g -o bin/QAnsel -lm -I/usr/include/SDL2 -D_REENTRANT -lSDL2 -lOpenCL -pthread - #rm -f src/*.cl.c + #rm -f src/*.cl.c \ No newline at end of file diff --git a/bin/QAnsel b/bin/QAnsel index da2cdeb..df10cea 100755 Binary files a/bin/QAnsel and b/bin/QAnsel differ diff --git a/examples/bellstate.txt b/examples/bellstate.txt index 31fe104..8ad1845 100644 --- a/examples/bellstate.txt +++ b/examples/bellstate.txt @@ -2,4 +2,4 @@ qreg q[2]; h q[0]; cx q[0], q[1]; -born; +born q; diff --git a/examples/decoherence.txt b/examples/decoherence.txt index c4ac0ed..2d59d95 100644 --- a/examples/decoherence.txt +++ b/examples/decoherence.txt @@ -9,4 +9,4 @@ h q[0]; cx q[0], q[1]; h q[0]; measure q[0] -> c[0]; -sample; +sample c; diff --git a/src/QAnsel.c b/src/QAnsel.c index 70b9a53..f232e4a 100644 --- a/src/QAnsel.c +++ b/src/QAnsel.c @@ -1,1428 +1,741 @@ -#include -#include -#include -#include -#include "complex.c" -#include "gates.c" -#include "display.c" -#include "chacha20.c" -#define QUBITS_MAX 14 -unsigned char HIDDEN_VARIABLE = 0; -FILE* RANDOM_FILE; -#define GPU_ENABLED -unsigned char USE_THREADS = 1; -#define MODE_BARE 1 -#define MODE_THREADED 2 -#define MODE_METAL 3 -#define MODE_METAL_THREADED 4 -unsigned char MODE = MODE_BARE; -//#define SPEED_TEST +#include +#include "core.c" -typedef struct +void qansel_read_script(char* script, char*** chunksReturn, int** chunkLinesReturn, int* countReturn) { - char n[128]; - unsigned char q0, q1, q2; - float arg0, arg1, arg2; -} QInstr; - -float qansel_rand_s(float s) -{ - unsigned int tmp; - memcpy(&tmp, &s, sizeof(unsigned int)); - srand(tmp); -} -float qansel_rand_h() -{ - return ((float)rand()) / ((float)RAND_MAX); -} -float qansel_rand_t() -{ - if (RANDOM_FILE) + size_t scriptSize = strlen(script); + char* line = malloc(0); + char** chunks = malloc(0); + int* chunksAssociatedLines = malloc(0); + int lineCount = 1; + int lineLen = 0; + int chunkCount = 0; + int inComment = 0; + for (int i = 0; i < scriptSize; i++) { - unsigned int num = 0; - for (unsigned char i = 0; i < 4; i++) + int charactersLeft = scriptSize - i; + if (script[i] == '\n') { - num = (num << 8) | fgetc(RANDOM_FILE); + lineCount++; + inComment = 0; + } + else if (charactersLeft >= 2 && script[i] == '/' && script[i + 1] == '/') + { + inComment = 1; + } + else if (!inComment && script[i] != ';' && script[i] != '{' && script[i] != '}') + { + line = realloc(line, lineLen + 1); + line[lineLen++] = script[i] == '\t' ? ' ' : script[i]; + if (script[i] == ')' && lineLen > 2) + { + for (int j = 0; j < lineLen - 1; j++) + { + if ( (line[j] == 'i' || line[j] == 'I') && (line[j + 1] == 'f' || line[j + 1] == 'F') ) + { + line = realloc(line, lineLen + 1); + line[lineLen++] = 0; + chunks = realloc(chunks, (chunkCount + 1) * sizeof(char*)); + chunksAssociatedLines = realloc(chunksAssociatedLines, (chunkCount + 1) * sizeof(int)); + chunks[chunkCount] = line; + chunksAssociatedLines[chunkCount++] = lineCount; + line = malloc(0); + lineLen = 0; + break; + } + } + } + } + else if (!inComment && (script[i] == '{' || script[i] == '}')) + { + if (lineLen > 0) + { + line = realloc(line, lineLen + 1); + line[lineLen++] = 0; + chunks = realloc(chunks, (chunkCount + 1) * sizeof(char*)); + chunksAssociatedLines = realloc(chunksAssociatedLines, (chunkCount + 1) * sizeof(int)); + chunks[chunkCount] = line; + chunksAssociatedLines[chunkCount++] = lineCount; + line = malloc(2); + } + else + { + line = realloc(line, 2); + } + line[0] = script[i]; + line[1] = 0; + chunks = realloc(chunks, (chunkCount + 1) * sizeof(char*)); + chunksAssociatedLines = realloc(chunksAssociatedLines, (chunkCount + 1) * sizeof(int)); + chunks[chunkCount] = line; + chunksAssociatedLines[chunkCount++] = lineCount; + line = malloc(0); + lineLen = 0; + } + else if (!inComment && script[i] == ';') + { + if (lineLen > 0) + { + line = realloc(line, lineLen + 1); + line[lineLen++] = 0; + chunks = realloc(chunks, (chunkCount + 1) * sizeof(char*)); + chunksAssociatedLines = realloc(chunksAssociatedLines, (chunkCount + 1) * sizeof(int)); + chunks[chunkCount] = line; + chunksAssociatedLines[chunkCount++] = lineCount; + line = malloc(0); + lineLen = 0; + } } - return ((float)num) / ((float)UINT32_MAX); - } - else - { - HIDDEN_VARIABLE = 1; - return qansel_rand_h(); - } -} - -float qansel_rand() -{ - return HIDDEN_VARIABLE ? qansel_rand_h() : qansel_rand_t(); -} - -void qansel_cnot(cpx_mtx_t* stateVector, unsigned char qubitCount, unsigned char bitA, unsigned char bitB) -{ - unsigned int retLen = (unsigned int)pow(2, qubitCount); - cpx_mtx_t ret; - cpx_mtx_init(&ret, 1, retLen); - cpx_t n; - for (unsigned int i = 0; i < retLen; i++) - { - unsigned char bitAVal = (i >> bitA) & 1; - unsigned char bitBVal = (i >> bitB) & 1; - unsigned char bitBNew = bitAVal ? !bitBVal : bitBVal; - unsigned int j = (i & ~(1 << bitB)) | (bitBNew << bitB); - cpx_mtx_get(stateVector, 0, i, &n); - cpx_mtx_set(&ret, 0, j, &n); } - cpx_mtx_free(stateVector); - stateVector->ptr = ret.ptr; - stateVector->rows = ret.rows; - stateVector->cols = ret.cols; -} - -void qansel_swap(cpx_mtx_t* stateVector, unsigned char qubitCount, unsigned char bitA, unsigned char bitB) -{ - unsigned int retLen = (unsigned int)pow(2, qubitCount); - cpx_mtx_t ret; - cpx_mtx_init(&ret, 1, retLen); - cpx_t n; - for (unsigned int i = 0; i < retLen; i++) + if (lineLen > 0) { - unsigned char bitAVal = (i >> bitA) & 1; - unsigned char bitBVal = (i >> bitB) & 1; - unsigned char bitANew = bitBVal; - unsigned char bitBNew = bitAVal; - unsigned int j = (i & ~((1 << bitA) | (1 << bitB))) | ((bitANew << bitA) | (bitBNew << bitB)); - cpx_mtx_get(stateVector, 0, i, &n); - cpx_mtx_set(&ret, 0, j, &n); + line = realloc(line, lineLen + 1); + line[lineLen++] = 0; + chunks = realloc(chunks, (chunkCount + 1) * sizeof(char*)); + chunksAssociatedLines = realloc(chunksAssociatedLines, (chunkCount + 1) * sizeof(int)); + chunks[chunkCount] = line; + chunksAssociatedLines[chunkCount++] = lineCount; } - cpx_mtx_free(stateVector); - stateVector->ptr = ret.ptr; - stateVector->rows = ret.rows; - stateVector->cols = ret.cols; -} - -void qansel_fredkin(cpx_mtx_t* stateVector, unsigned char qubitCount, unsigned char bitA, unsigned char bitB, unsigned char bitC) -{ - unsigned int retLen = (unsigned int)pow(2, qubitCount); - cpx_mtx_t ret; - cpx_mtx_init(&ret, 1, retLen); - cpx_t n; - for (unsigned int i = 0; i < retLen; i++) + else { - unsigned char bitAVal = (i >> bitA) & 1; - unsigned char bitBVal = (i >> bitB) & 1; - unsigned char bitCVal = (i >> bitC) & 1; - unsigned char bitBNew = bitAVal ? bitCVal : bitBVal; - unsigned char bitCNew = bitAVal ? bitBVal : bitCVal; - unsigned int j = (i & ~((1 << bitB) | (1 << bitC))) | ((bitBNew << bitB) | (bitCNew << bitC)); - cpx_mtx_get(stateVector, 0, i, &n); - cpx_mtx_set(&ret, 0, j, &n); + free(line); } - cpx_mtx_free(stateVector); - stateVector->ptr = ret.ptr; - stateVector->rows = ret.rows; - stateVector->cols = ret.cols; -} - - -void qansel_toffoli(cpx_mtx_t* stateVector, unsigned char qubitCount, unsigned char bitA, unsigned char bitB, unsigned char bitC) -{ - unsigned int retLen = (unsigned int)pow(2, qubitCount); - cpx_mtx_t ret; - cpx_mtx_init(&ret, 1, retLen); - cpx_t n; - for (unsigned int i = 0; i < retLen; i++) + for (int i = 0; i < chunkCount; i++) { - unsigned char bitAVal = (i >> bitA) & 1; - unsigned char bitBVal = (i >> bitB) & 1; - unsigned char bitCVal = (i >> bitC) & 1; - unsigned char bitCNew = (bitAVal && bitBVal) ? !bitCVal : bitCVal; - unsigned int j = (i & ~(1 << bitC)) | (bitCNew << bitC); - cpx_mtx_get(stateVector, 0, i, &n); - cpx_mtx_set(&ret, 0, j, &n); + int len = strlen(chunks[i]); + for (int j = 0; j < len; j++) + { + if (chunks[i][j] >= 'A' && chunks[i][j] <= 'Z') + { + chunks[i][j] += 'a' - 'A'; + } + } } - cpx_mtx_free(stateVector); - stateVector->ptr = ret.ptr; - stateVector->rows = ret.rows; - stateVector->cols = ret.cols; -} - -float* qansel_unitary(float theta, float phi, float lambda) -{ - cpx_mtx_t m; - cpx_t a, b, c, d; - a.real = cos(theta/2.0); - a.imaginary = 0; - b.real = -cos(lambda) * sin(theta/2.0); - b.imaginary = sin(lambda) * sin(theta/2.0); - c.real = cos(phi) * sin(theta/2.0); - c.imaginary = sin(phi) * sin(theta/2.0); - d.real = cos(phi + lambda) * cos(theta/2.0); - d.imaginary = sin(phi + lambda) * cos(theta/2.0); - cpx_mtx_init(&m, 2, 2); - cpx_mtx_set(&m, 0, 0, &a); - cpx_mtx_set(&m, 0, 1, &b); - cpx_mtx_set(&m, 1, 0, &c); - cpx_mtx_set(&m, 1, 1, &d); - return m.ptr; + *chunksReturn = chunks; + *chunkLinesReturn = chunksAssociatedLines; + *countReturn = chunkCount; } -void qansel_instruction(cpx_mtx_t* stateVector, unsigned char qubitCount, QInstr* instr) +float qansel_parse_float_part(char* neg, char* str) { - cpx_mtx_t tmp; - cpx_mtx_t gate; - gate.rows = 2; - gate.cols = 2; - float* gate_ptr; - switch (instr->n[0]) - { - case 'h': gate_ptr = Hadamard; break; - case 'x': gate_ptr = PauliX; break; - case 'y': gate_ptr = PauliY; break; - case 'z': gate_ptr = PauliZ; break; - case 's': gate_ptr = PhaseS; break; - case 't': gate_ptr = PhaseT; break; - case 'u': - gate_ptr = qansel_unitary(instr->arg0, instr->arg1, instr->arg2); - break; - default: gate_ptr = Identity; break; - } - - cpx_t n; - cpx_mtx_t filter; - cpx_mtx_init(&filter, 2, 2); - unsigned char qubit = qubitCount - (instr->q0) - 1; - if (qubit == 0) - { - memcpy(filter.ptr, gate_ptr, 8 * sizeof(float)); - } - else + float ret; + int len = strlen(str); + if (len > 2) { - memcpy(filter.ptr, Identity, 8 * sizeof(float)); - } - - for (unsigned char i = 1; i < qubitCount; i++) - { - if (qubit == i) - { - gate.ptr = gate_ptr; - } - else - { - gate.ptr = Identity; - } - - tmp.rows = filter.rows * gate.rows; - tmp.cols = filter.cols * gate.cols; - tmp.ptr = malloc(tmp.rows * (tmp.cols * 2) * sizeof(float)); - - #ifdef SPEED_TEST - printf("(%ix%i);(%ix%i) (knk)\n", tmp.rows, tmp.cols, gate.rows, gate.cols); - unsigned long int us1, us2; - us1 = get_time(); - cpx_mtx_knk_metal(tmp.ptr, filter.ptr, gate.ptr, filter.rows, filter.cols, gate.rows, gate.cols); - us2 = get_time(); - printf("\tMetal: %lu\n", us2 - us1); - us1 = get_time(); - cpx_mtx_knk_metal_2x2(tmp.ptr, filter.ptr, gate.ptr, filter.rows, filter.cols, gate.rows, gate.cols); - us2 = get_time(); - printf("\tMetal2x2: %lu\n", us2 - us1); - us1 = get_time(); - cpx_mtx_knk_threads(tmp.ptr, filter.ptr, gate.ptr, filter.rows, filter.cols, gate.rows, gate.cols); - us2 = get_time(); - printf("\tThreads: %lu\n", us2 - us1); - us1 = get_time(); - cpx_mtx_knk_threads_2x2(tmp.ptr, filter.ptr, gate.ptr, filter.rows, filter.cols, gate.rows, gate.cols); - us2 = get_time(); - printf("\tThreads2x2: %lu\n", us2 - us1); - us1 = get_time(); - cpx_mtx_knk(tmp.ptr, filter.ptr, gate.ptr, filter.rows, filter.cols, gate.rows, gate.cols); - us2 = get_time(); - printf("\tBare: %lu\n", us2 - us1); - us1 = get_time(); - cpx_mtx_knk_2x2(tmp.ptr, filter.ptr, gate.ptr, filter.rows, filter.cols, gate.rows, gate.cols); - us2 = get_time(); - printf("\tBare2x2: %lu\n", us2 - us1); - - //us1 = get_time(); - //cpx_mtx_knk(tmp.ptr, filter.ptr, gate.ptr, filter.rows, filter.cols, gate.rows, gate.cols); - //us2 = get_time(); - //printf("\tTranspose: %lu\n", us2 - us1); - #else - if (MODE == MODE_METAL && tmp.cols >= 64) + ret = atof(str); + if (str[len - 2] == 'p' && str[len - 1] == 'i') { - cpx_mtx_knk_metal_2x2(tmp.ptr, filter.ptr, gate.ptr, filter.rows, filter.cols, gate.rows, gate.cols); + ret *= M_PI; } - else if ((MODE == MODE_THREADED || MODE == MODE_METAL_THREADED) && tmp.cols >= 64) - { - cpx_mtx_knk_threads_2x2(tmp.ptr, filter.ptr, gate.ptr, filter.rows, filter.cols, gate.rows, gate.cols); - } - else - { - cpx_mtx_knk_2x2(tmp.ptr, filter.ptr, gate.ptr, filter.rows, filter.cols, gate.rows, gate.cols); - } - #endif - - free(filter.ptr); - filter.ptr = tmp.ptr; - filter.rows = tmp.rows; - filter.cols = tmp.cols; } - - cpx_mtx_init(&tmp, stateVector->rows, stateVector->cols); - - #ifdef SPEED_TEST - printf("%ix%i (dot)\n", tmp.rows, tmp.cols); - unsigned long int us1, us2; - us1 = get_time(); - cpx_mtx_dot_metal(tmp.ptr, stateVector->ptr, filter.ptr, stateVector->rows, stateVector->cols, filter.rows, filter.cols); - us2 = get_time(); - printf("\tMetal: %lu\n", us2 - us1); - us1 = get_time(); - cpx_mtx_dot_threads(tmp.ptr, stateVector->ptr, filter.ptr, stateVector->rows, stateVector->cols, filter.rows, filter.cols); - us2 = get_time(); - printf("\tThreads: %lu\n", us2 - us1); - us1 = get_time(); - cpx_mtx_dot(tmp.ptr, stateVector->ptr, filter.ptr, stateVector->rows, stateVector->cols, filter.rows, filter.cols); - us2 = get_time(); - printf("\tBare: %lu\n", us2 - us1); - #else - if ((MODE == MODE_METAL || MODE == MODE_METAL_THREADED) && tmp.cols >= 64) + else if (strcmp(str, "pi") == 0) { - cpx_mtx_dot_metal(tmp.ptr, stateVector->ptr, filter.ptr, stateVector->rows, stateVector->cols, filter.rows, filter.cols); + ret = M_PI; } - else if (MODE == MODE_THREADED && tmp.cols >= 64) + else { - cpx_mtx_dot_threads(tmp.ptr, stateVector->ptr, filter.ptr, stateVector->rows, stateVector->cols, filter.rows, filter.cols); + ret = atof(str); } - else + if (strcmp(neg, "-") == 0) { - cpx_mtx_dot(tmp.ptr, stateVector->ptr, filter.ptr, stateVector->rows, stateVector->cols, filter.rows, filter.cols); + ret *= -1; } - #endif - free(stateVector->ptr); - stateVector->ptr = tmp.ptr; - free(filter.ptr); - if (instr->n[0] == 'u') free(gate_ptr); + return ret; } -unsigned char qansel_measure(cpx_mtx_t* stateVector, unsigned char qubitCount, unsigned char qubit) +int qansel_parse_float(char* str, float* returnFloat) { - unsigned int qubitCountPow2 = (unsigned int)pow(2, qubitCount); - cpx_t n; - float prob0 = 0; - for (unsigned int i = 0; i < qubitCountPow2; i++) + *returnFloat = 0; + const char expr[] = "^(-|)([0-9][0-9]*\\.[0-9]*|[0-9][0-9]*|[0-9][0-9]*\\.[0-9]*pi|[0-9][0-9]*pi|pi)([/](-|)([0-9][0-9]*\\.[0-9]*|[0-9][0-9]*|[0-9][0-9]*\\.[0-9]*pi|[0-9][0-9]*pi|pi)|)$"; + regex_t regex; + regmatch_t regmatches[10]; + if (regcomp(®ex, expr, REG_EXTENDED | REG_ICASE)) return 0; + int ret = regexec(®ex, str, 10, regmatches, 0); + if (!ret) { - unsigned char bit = (i >> qubit) & 1; - cpx_mtx_get(stateVector, 0, i, &n); - if (bit == 0) prob0 += cpx_magsqr(&n); + int strbeg = regmatches[1].rm_so; + int strlen = regmatches[1].rm_eo - regmatches[1].rm_so; + char neg1[strlen + 1]; + memcpy(neg1, str + strbeg, strlen); + neg1[strlen] = 0; + + strbeg = regmatches[2].rm_so; + strlen = regmatches[2].rm_eo - regmatches[2].rm_so; + char numer[strlen + 1]; + memcpy(numer, str + strbeg, strlen); + numer[strlen] = 0; + *returnFloat = qansel_parse_float_part(neg1, numer); + + if (regmatches[3].rm_eo > regmatches[3].rm_so) + { + strbeg = regmatches[4].rm_so; + strlen = regmatches[4].rm_eo - regmatches[4].rm_so; + char neg2[strlen + 1]; + memcpy(neg2, str + strbeg, strlen); + neg2[strlen] = 0; + + strbeg = regmatches[5].rm_so; + strlen = regmatches[5].rm_eo - regmatches[5].rm_so; + char denom[strlen + 1]; + memcpy(denom, str + strbeg, strlen); + denom[strlen] = 0; + + float fdenom = qansel_parse_float_part(neg2, denom); + *returnFloat /= fdenom; + } } - - float r = qansel_rand(); - unsigned char newBit = r < prob0 ? 0 : 1; - float probTot = 0; - for (unsigned int i = 0; i < qubitCountPow2; i++) + else if (ret == REG_NOMATCH) { - unsigned char bit = (i >> qubit) & 1; - cpx_mtx_get(stateVector, 0, i, &n); - if (bit != newBit) - { - n.real = 0; - n.imaginary = 0; - } - else - { - probTot += cpx_magsqr(&n); - } - cpx_mtx_set(stateVector, 0, i, &n); + return 0; } - - float multiplier = sqrt(1 / probTot); - for (unsigned int i = 0; i < qubitCountPow2; i++) + else { - unsigned char bit = (i >> qubit) & 1; - cpx_mtx_get(stateVector, 0, i, &n); - if (bit == newBit) - { - n.real *= multiplier; - n.imaginary *= multiplier; - } - cpx_mtx_set(stateVector, 0, i, &n); + char errbuf[100]; + regerror(ret, ®ex, errbuf, sizeof(errbuf)); + fprintf(stderr, "QAnsel: %s.\n", errbuf); + exit(1); } + regfree(®ex); - return newBit; + return 1; } -void qansel_run(unsigned char qubitCount, unsigned char bitCount, QInstr* instr, unsigned char* retBitVect, unsigned int instrLen, unsigned char gfx) +int qansel_process_chunk(int index, char* chunk, int line, regmatch_t* regmatches, int* qubitCount, int* bitCount, unsigned char* binary, int* binarySize) { - unsigned int qubitCountPow2 = (unsigned int)pow(2, qubitCount); - - unsigned char bitVector[bitCount]; - cpx_mtx_t stateVector; - cpx_mtx_init(&stateVector, 1, qubitCountPow2); - cpx_mtx_set2(&stateVector, 0, 0, 1, 0); - if (gfx) display(&stateVector, qubitCount); - unsigned char flags; - - for (unsigned char i = 0; i < bitCount; i++) bitVector[i] = 0; - - unsigned long int ns, ps; - for (unsigned int i = 0; i < instrLen; i++) + unsigned short s0; + float d0, d1, d2; + unsigned char instr = 0; + unsigned char a0 = 0; + unsigned char a1 = 0; + unsigned char a2 = 0; + if (index == 0) //qreg { - //ns = get_time(); - //if (i > 0) - //{ - // printf("%s: %lu\n", instr[i].n, ns - ps); - //} - //ps = ns; - - cpx_t qqq; - cpx_mtx_get(&stateVector, 0, 0, &qqq); - if (strcmp(instr[i].n, "measure") == 0) - { - bitVector[instr[i].q1] = qansel_measure(&stateVector, qubitCount, instr[i].q0); - } - else if (strcmp(instr[i].n, "cswap") == 0) - { - qansel_fredkin(&stateVector, qubitCount, instr[i].q0, instr[i].q1, instr[i].q2); - } - else if (strcmp(instr[i].n, "ccx") == 0) + if (*qubitCount > 0) { - qansel_toffoli(&stateVector, qubitCount, instr[i].q0, instr[i].q1, instr[i].q2); + fprintf(stderr, "QAnsel on line %i: Qubits can only be initialized once.\n", line); + return 0; } - else if (strcmp(instr[i].n, "cx") == 0) + int strbeg = regmatches[1].rm_so; + int strlen = regmatches[1].rm_eo - regmatches[1].rm_so; + char tmp[strlen + 1]; + memcpy(tmp, chunk + strbeg, strlen); + tmp[strlen] = 0; + int nump = atoi(tmp); + if (nump > QUBITS_MAX) { - qansel_cnot(&stateVector, qubitCount, instr[i].q0, instr[i].q1); + fprintf(stderr, "QAnsel on line %i: Initialized qubits cannot exceed %i.\n", line, QUBITS_MAX); + return 0; } - else if (strcmp(instr[i].n, "swap") == 0) - { - qansel_swap(&stateVector, qubitCount, instr[i].q0, instr[i].q1); - } - else if (strcmp(instr[i].n, "if_all") == 0) - { - unsigned char val = 0; - for (int32_t j = bitCount - 1; j >= 0; j--) - { - val = (val << 1) | bitVector[j]; - } - if (val != instr[i].q0) i++; - } - else if (strcmp(instr[i].n, "if") == 0) - { - if (bitVector[instr[i].q0] != instr[i].q1) i++; - } - else if (strcmp(instr[i].n, "printq_all") == 0) - { - printf("[ "); cpx_mtx_print(&stateVector); printf(" ]\n"); - } - else if (strcmp(instr[i].n, "printc_all") == 0) + *qubitCount = nump; + } + else if (index == 1) //creg + { + if (*bitCount > 0) { - for (int32_t j = bitCount - 1; j >= 0; j--) - { - putchar('0' + bitVector[j]); - } - putchar('\n'); + fprintf(stderr, "QAnsel on line %i: Classical bits can only be initialized once.\n", line); + return 0; } - else if (strcmp(instr[i].n, "printc") == 0) + int strbeg = regmatches[1].rm_so; + int strlen = regmatches[1].rm_eo - regmatches[1].rm_so; + char tmp[strlen + 1]; + memcpy(tmp, chunk + strbeg, strlen); + tmp[strlen] = 0; + int nump = atoi(tmp); + if (nump > QUBITS_MAX) { - putchar('0' + bitVector[instr[i].q0]); - putchar('\n'); + fprintf(stderr, "QAnsel on line %i: Initialized classical bits cannot exceed %i.\n", line, QUBITS_MAX); + return 0; } - else if (strcmp(instr[i].n, "printq") == 0 || strcmp(instr[i].n, "density") == 0) - { - cpx_mtx_t tmp; - cpx_mtx_init(&tmp, 1, 2); - for (unsigned int j = 0; j < qubitCountPow2; j++) - { - if ((j >> instr[i].q0) & 1) - { - cpx_t a, b; - cpx_mtx_get(&tmp, 0, 1, &a); - cpx_mtx_get(&stateVector, 0, j, &b); - a.real += b.real; - a.imaginary += b.imaginary; - cpx_mtx_set(&tmp, 0, 1, &a); - } - else + *bitCount = nump; + } + else if (index == 2 || index == 3 || index == 4 || index == 5) //single qubit instructions + { + if (*qubitCount == 0) + { + fprintf(stderr, "QAnsel on line %i: Quantum bit instruction used prior to initialization.\n", line); + return 0; + } + int rmp = 1; + { + int strbeg = regmatches[rmp].rm_so; + int strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so; + rmp++; + char tmp[strlen + 1]; + memcpy(tmp, chunk + strbeg, strlen); + tmp[strlen] = 0; + if (strcmp(tmp, "rx") == 0) instr = QANSEL_INSTRUCTION_RX; + else if (strcmp(tmp, "ry") == 0) instr = QANSEL_INSTRUCTION_RY; + else if (strcmp(tmp, "rz") == 0) instr = QANSEL_INSTRUCTION_RZ; + else if (strcmp(tmp, "u1") == 0) instr = QANSEL_INSTRUCTION_U1; + else if (strcmp(tmp, "u2") == 0) instr = QANSEL_INSTRUCTION_U2; + else if (strcmp(tmp, "u3") == 0) instr = QANSEL_INSTRUCTION_U3; + else if (strcmp(tmp, "u") == 0) instr = QANSEL_INSTRUCTION_U3; + else if (strcmp(tmp, "reset") == 0) instr = QANSEL_INSTRUCTION_RESET; + else if (strcmp(tmp, "barrier") == 0) instr = QANSEL_INSTRUCTION_BARRIER; + else if (strcmp(tmp, "born") == 0) instr = QANSEL_INSTRUCTION_BORN; + else if (strcmp(tmp, "density") == 0) instr = QANSEL_INSTRUCTION_DENSITY; + else if (strcmp(tmp, "print") == 0) instr = QANSEL_INSTRUCTION_PRINT; + else if (strcmp(tmp, "not") == 0) instr = QANSEL_INSTRUCTION_X; + else if (strcmp(tmp, "x") == 0) instr = QANSEL_INSTRUCTION_X; + else if (strcmp(tmp, "y") == 0) instr = QANSEL_INSTRUCTION_Y; + else if (strcmp(tmp, "z") == 0) instr = QANSEL_INSTRUCTION_Z; + else if (strcmp(tmp, "h") == 0) instr = QANSEL_INSTRUCTION_H; + else if (strcmp(tmp, "s") == 0) instr = QANSEL_INSTRUCTION_S; + else if (strcmp(tmp, "t") == 0) instr = QANSEL_INSTRUCTION_T; + } + for (int i = 0; i < (index == 2 ? 0 : (index == 3 ? 1 : (index == 4 ? 2 : 3))); i++) + { + int strbeg = regmatches[rmp].rm_so; + int strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so; + rmp++; + char tmp[strlen + 1]; + memcpy(tmp, chunk + strbeg, strlen); + tmp[strlen] = 0; + if (!qansel_parse_float(tmp, (i == 0 ? &d0 : (i == 1 ? &d1 : &d2)))) + { + fprintf(stderr, "QAnsel on line %i: Invalid rotation value.\n", line); + return 0; + } + } + { + int strbeg = regmatches[rmp].rm_so; + int strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so; + rmp++; + if (strlen > 0) + { + strbeg = regmatches[rmp].rm_so; + strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so; + rmp++; + char tmp[strlen + 1]; + memcpy(tmp, chunk + strbeg, strlen); + tmp[strlen] = 0; + a0 = atoi(tmp); + if (a0 >= *qubitCount) { - cpx_t a, b; - cpx_mtx_get(&tmp, 0, 0, &a); - cpx_mtx_get(&stateVector, 0, j, &b); - a.real += b.real; - a.imaginary += b.imaginary; - cpx_mtx_set(&tmp, 0, 0, &a); + fprintf(stderr, "QAnsel on line %i: Index `%i` exceeds allocated quantum bits.\n", line, a0); + return 0; } } - float multiplier = 0; - cpx_t n; - cpx_mtx_get(&tmp, 0, 0, &n); - multiplier += cpx_magsqr(&n); - cpx_mtx_get(&tmp, 0, 1, &n); - multiplier += cpx_magsqr(&n); - multiplier = sqrt(1 / multiplier); - n.real *= multiplier; - n.imaginary *= multiplier; - cpx_mtx_set(&tmp, 0, 1, &n); - cpx_mtx_get(&tmp, 0, 0, &n); - n.real *= multiplier; - n.imaginary *= multiplier; - cpx_mtx_set(&tmp, 0, 0, &n); - - if (strcmp(instr[i].n, "density") == 0) - { - cpx_t a, b, c, d, x, y, z, w; - cpx_mtx_get(&tmp, 0, 0, &a); - cpx_mtx_get(&tmp, 0, 1, &b); - cpx_mtx_get(&tmp, 0, 0, &c); - cpx_mtx_get(&tmp, 0, 1, &d); - c.imaginary *= -1; - d.imaginary *= -1; - cpx_mul(&x, &a, &c); - cpx_mul(&y, &a, &d); - cpx_mul(&z, &b, &c); - cpx_mul(&w, &b, &d); - char* sx = cpx_str(&x); - char* sy = cpx_str(&y); - char* sz = cpx_str(&z); - char* sw = cpx_str(&w); - printf("[ %s, %s ]\n", sx, sy); - printf("[ %s, %s ]\n", sz, sw); - free(sx); - free(sy); - free(sz); - free(sw); - } else { - printf("[ "); cpx_mtx_print(&tmp); printf(" ]\n"); - } - cpx_mtx_free(&tmp); - } - else if (strcmp(instr[i].n, "born_all") == 0) - { - for (unsigned int j = 0; j < qubitCountPow2; j++) - { - unsigned int tmp = j; - for (unsigned char k = 0; k < qubitCount; k++) + a0 = 0x0F; + if (instr == QANSEL_INSTRUCTION_DENSITY) { - putchar('0' + (tmp >> (qubitCount - 1) & 1)); - tmp <<= 1; + fprintf(stderr, "QAnsel on line %i: Density matrices can only be produced for individual qubits.\n", line, a0); + return 0; } - cpx_t n; - cpx_mtx_get(&stateVector, 0, j, &n); - printf(": %.1f%%\n", cpx_magsqr(&n) * 100); - } - } - else if (strcmp(instr[i].n, "born") == 0) - { - float prob = 0; - for (unsigned int j = 0; j < qubitCountPow2; j++) - { - cpx_t n; - cpx_mtx_get(&stateVector, 0, j, &n); - if ((j >> instr[i].q0) & 1) - { - prob += cpx_magsqr(&n); - } - } - printf("0: %.1f%%\n", (1 - prob) * 100.0); - printf("1: %.1f%%\n", prob * 100.0); - } - else if (strcmp(instr[i].n, "hvar") == 0) - { - HIDDEN_VARIABLE = 1; - float tmp1 = (float)instr[i].arg0; - unsigned int tmp2; - memcpy(&tmp2, &tmp1, sizeof(unsigned int)); - srand(tmp2); - } - else if (strcmp(instr[i].n, "rand") == 0) - { - HIDDEN_VARIABLE = 0; - } - else if (strcmp(instr[i].n, "reset_all") == 0) - { - cpx_mtx_set2(&stateVector, 0, 0, 1, 0); - for (unsigned int j = 1; j < qubitCountPow2; j++) - { - cpx_mtx_set2(&stateVector, 0, j, 0, 0); - } - for (unsigned char j = 0; j < bitCount; j++) - { - bitVector[j] = 0; } } - else if (strcmp(instr[i].n, "resetq") == 0) + switch (index) { - unsigned char bit = qansel_measure(&stateVector, qubitCount, instr[i].q0); - if (bit) - { - instr[i].n[0] = 'x'; - instr[i].n[1] = 0; - qansel_instruction(&stateVector, qubitCount, instr + i); - } - } - else if (strcmp(instr[i].n, "resetc") == 0) - { - bitVector[instr[i].q0] = 0; - } - else - { - qansel_instruction(&stateVector, qubitCount, instr + i); - } - - if (gfx) display(&stateVector, qubitCount); - } - display(NULL, -1); - - cpx_mtx_free(&stateVector); - - if (retBitVect != NULL) - { - for (unsigned int i = 0; i < bitCount; i++) - { - retBitVect[i] = bitVector[i]; + case 2: + *binarySize += 2 + sizeof(float) * 0; + binary = realloc(binary, *binarySize); + binary[*binarySize - 2] = instr; + binary[*binarySize - 1] = a0; + break; + case 3: + *binarySize += 2 + sizeof(float) * 1; + binary = realloc(binary, *binarySize); + binary[*binarySize - 2 - sizeof(float) * 1] = instr; + binary[*binarySize - 1 - sizeof(float) * 1] = a0; + memcpy(binary + (*binarySize - sizeof(float)), &d0, sizeof(float)); + break; + case 4: + *binarySize += 2 + sizeof(float) * 2; + binary = realloc(binary, *binarySize); + binary[*binarySize - 2 - sizeof(float) * 2] = instr; + binary[*binarySize - 1 - sizeof(float) * 2] = a0; + memcpy(binary + (*binarySize - sizeof(float) * 2), &d0, sizeof(float)); + memcpy(binary + (*binarySize - sizeof(float) * 1), &d1, sizeof(float)); + break; + case 5: + *binarySize += 2 + sizeof(float) * 3; + binary = realloc(binary, *binarySize); + binary[*binarySize - 2 - sizeof(float) * 3] = instr; + binary[*binarySize - 1 - sizeof(float) * 3] = a0; + memcpy(binary + (*binarySize - sizeof(float) * 3), &d0, sizeof(float)); + memcpy(binary + (*binarySize - sizeof(float) * 2), &d1, sizeof(float)); + memcpy(binary + (*binarySize - sizeof(float) * 1), &d2, sizeof(float)); + break; } } - -} - -void process(int argc, char** argv) -{ - struct timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - float seed = (float)((unsigned long)ts.tv_sec * 1000000000LL + ts.tv_nsec); - qansel_rand_s(seed); - char** lines = malloc(0); - unsigned int* lineIDs = malloc(0); - char* text = malloc(0); - unsigned int textLen = 0; - unsigned int linesLen = 0; - int c; - int pc = -1; - unsigned char comment = 0; - unsigned char commentM = 0; - unsigned int lineID = 1; - unsigned char skipSpaces = 1; - unsigned char inGate = 0; - unsigned char fullSample = 0; - while ( (c = getchar()) != EOF ) + else if (index == 6) //measure instruction { - if (c == '/' && commentM == 0 && comment == 0) - { - commentM = 1; - } - else if (c == '/' && commentM == 1 && comment == 0) - { - comment = 1; - commentM = 0; - } - else if (c == '\n') + if (*qubitCount == 0) { - comment = 0; - commentM = 0; - lineID += 1; + fprintf(stderr, "QAnsel on line %i: Quantum bit instruction used prior to initialization.\n", line); + return 0; } - else if (comment || (c == ' ' && skipSpaces)) {} - else if (c != '\n' && c != '\t' && c != ';' && (c != ')' || inGate)) + if (*bitCount == 0) { - if (commentM == 1) - { - text = realloc(text, textLen + 1); - text[textLen++] = '/'; - commentM = 0; - } - skipSpaces = 0; - if (c >= 'A' && c <= 'Z') c += 'a' - 'A'; - if (c == 'u') inGate = 1; - if (c == 'r') inGate = 1; - text = realloc(text, textLen + 1); - text[textLen++] = c; - pc = c; + fprintf(stderr, "QAnsel on line %i: Classical bit instruction used prior to initialization.\n", line); + return 0; } - else if (c == ';' || (c == ')' && !inGate)) + int rmp = 1; { - inGate = 0; - skipSpaces = 1; - if (c == ')') + int strbeg = regmatches[rmp].rm_so; + int strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so; + rmp++; + if (strlen > 0) { - text = realloc(text, textLen + 1); - text[textLen++] = ')'; - } - text = realloc(text, textLen + 1); - text[textLen++] = 0; - lineIDs = realloc(lineIDs, (linesLen + 1) * sizeof(unsigned int)); - lineIDs[linesLen] = lineID; - lines = realloc(lines, (linesLen + 1) * sizeof(char*)); - lines[linesLen] = malloc(strlen(text) + 1); - strcpy(lines[linesLen++], text); - text = realloc(text, 0); - textLen = 0; - pc = ';'; - } - } - text = realloc(text, textLen + 1); - text[textLen++] = 0; - if (strlen(text) > 0) - { - free(text); - fprintf(stderr, "QAnsel: Invalid trailing text"); - exit(1); - } - free(text); - - unsigned char qubitCount = 0xFF; - unsigned char bitCount = 0xFF; - QInstr* instr = malloc(0); - unsigned int instrLen = 0; - unsigned char doDisplay = 0; - unsigned char errFound = 0; - for (unsigned int i = 0; i < linesLen; i++) - { - lineID = i; - - char g; - int q0, q1, q2; - float a0, a1, a2; - unsigned int matchedCount; - unsigned int lineLen = strlen(lines[i]); - if (lineLen > 1) - { - while (lineLen > 1 && (lines[i][lineLen - 1] == ' ' || lines[i][lineLen - 1] == '\t')) - { - lines[i][lineLen - 1] = 0; - lineLen--; - } - } - - if (sscanf(lines[i], "qreg q[%i]%n", &q0, &matchedCount) == 1) - { - if (qubitCount == 0xFF) - { - qubitCount = q0; - if (qubitCount < 1 || qubitCount > QUBITS_MAX) + strbeg = regmatches[rmp].rm_so; + strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so; + rmp++; + char tmp[strlen + 1]; + memcpy(tmp, chunk + strbeg, strlen); + tmp[strlen] = 0; + a0 = atoi(tmp); + if (a0 >= *qubitCount) { - fprintf(stderr, "QAnsel: Invalid count"); - errFound = 1; - break; + fprintf(stderr, "QAnsel on line %i: Index `%i` exceeds allocated quantum bits.\n", line, a0); + return 0; } } else { - fprintf(stderr, "QAnsel: Repeated initialization"); - errFound = 1; - break; + a0 = 0x0F; } } - else if (sscanf(lines[i], "creg c[%i]%n", &q0, &matchedCount) == 1) { - if (bitCount == 0xFF) + int strbeg = regmatches[rmp].rm_so; + int strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so; + rmp++; + if (strlen > 0) { - bitCount = q0; - if (bitCount < 1 || bitCount > QUBITS_MAX) + strbeg = regmatches[rmp].rm_so; + strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so; + rmp++; + char tmp[strlen + 1]; + memcpy(tmp, chunk + strbeg, strlen); + tmp[strlen] = 0; + a1 = atoi(tmp); + if (a1 >= *bitCount) { - fprintf(stderr, "QAnsel: Invalid count"); - errFound = 1; - break; + fprintf(stderr, "QAnsel on line %i: Index `%i` exceeds allocated classical bits.\n", line, a1); + return 0; } + a1 += 0x10; } else { - fprintf(stderr, "QAnsel: Repeated initialization"); - errFound = 1; - break; - } - } - else if (sscanf(lines[i], "u(%f,%f,%f) q[%i]%n", &a0, &a1, &a2, &q0, &matchedCount) == 4) - { - if (qubitCount == 0xFF) - { - fprintf(stderr, "QAnsel: Instruction before initialization"); - errFound = 1; - break; + a1 = 0x1F; } - if (q0 < 0 || q0 >= qubitCount) - { - fprintf(stderr, "QAnsel: Invalid index"); - errFound = 1; - break; - } - instr = realloc(instr, (instrLen + 1) * sizeof(QInstr)); - instr[instrLen].n[0] = 'u'; - instr[instrLen].n[1] = 0; - instr[instrLen].q0 = q0; - instr[instrLen].arg0 = a0; - instr[instrLen].arg1 = a1; - instr[instrLen++].arg2 = a2; } - else if - ( - memcmp("rx(", lines[i], 3) == 0 - || memcmp("ry(", lines[i], 3) == 0 - || memcmp("rz(", lines[i], 3) == 0 - ) - { - float angle; - char ty; - if (sscanf(lines[i], "r%c(%f/%f) q[%i]%n", &ty, &a0, &a1, &q0, &matchedCount) == 4) - { - angle = a0 / a1; - } - else if (sscanf(lines[i], "r%c(%f/%fpi) q[%i]%n", &ty, &a0, &a1, &q0, &matchedCount) == 4) - { - angle = a0 / (a1 * M_PI); - } - else if (sscanf(lines[i], "r%c(%f/pi) q[%i]%n", &ty, &a0, &q0, &matchedCount) == 3) - { - angle = a0 / M_PI; - } - else if (sscanf(lines[i], "r%c(%f/-pi) q[%i]%n", &ty, &a0, &q0, &matchedCount) == 3) - { - angle = a0 / -M_PI; - } - else if (sscanf(lines[i], "r%c(%fpi/%f) q[%i]%n", &ty, &a0, &a1, &q0, &matchedCount) == 4) - { - angle = (a0 * M_PI) / a1; - } - else if (sscanf(lines[i], "r%c(pi/%f) q[%i]%n", &ty, &a0, &q0, &matchedCount) == 3) - { - angle = M_PI / a0; - } - else if (sscanf(lines[i], "r%c(-pi/%f) q[%i]%n", &ty, &a0, &q0, &matchedCount) == 3) - { - angle = -M_PI / a0; - } - else if (sscanf(lines[i], "r%c(%fpi/%fpi) q[%i]%n", &ty, &a0, &a1, &q0, &matchedCount) == 4) - { - angle = (a0 * M_PI) / (a1 * M_PI); - } - else if (sscanf(lines[i], "r%c(pi/pi) q[%i]%n", &ty, &q0, &matchedCount) == 2) - { - angle = 1; - } - else if (sscanf(lines[i], "r%c(-pi/pi) q[%i]%n", &ty, &q0, &matchedCount) == 2) - { - angle = -1; - } - else if (sscanf(lines[i], "r%c(pi/-pi) q[%i]%n", &ty, &q0, &matchedCount) == 2) - { - angle = -1; - } - else if (sscanf(lines[i], "r%c(-pi/-pi) q[%i]%n", &ty, &q0, &matchedCount) == 2) - { - angle = 1; - } - else if (sscanf(lines[i], "r%c(%fpi) q[%i]%n", &ty, &a0, &q0, &matchedCount) == 3) - { - angle = a0 * M_PI; - } - else if (sscanf(lines[i], "r%c(pi) q[%i]%n", &ty, &q0, &matchedCount) == 2) - { - angle = M_PI; - } - else if (sscanf(lines[i], "r%c(-pi) q[%i]%n", &ty, &q0, &matchedCount) == 2) - { - angle = -M_PI; - } - else if (sscanf(lines[i], "r%c(%f) q[%i]%n", &ty, &a0, &q0, &matchedCount) == 3) - { - angle = a0; + *binarySize += 3; + binary = realloc(binary, *binarySize); + binary[*binarySize - 3] = QANSEL_INSTRUCTION_MEASURE; + binary[*binarySize - 2] = a0; + binary[*binarySize - 1] = a1; + } + else if (index == 7) //classical bit instructions + { + if (*bitCount == 0) + { + fprintf(stderr, "QAnsel on line %i: Classical bit instruction used prior to initialization.\n", line); + return 0; + } + int rmp = 1; + { + int strbeg = regmatches[rmp].rm_so; + int strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so; + rmp++; + char tmp[strlen + 1]; + memcpy(tmp, chunk + strbeg, strlen); + tmp[strlen] = 0; + if (strcmp(tmp, "sample") == 0) instr = QANSEL_INSTRUCTION_SAMPLE; + else if (strcmp(tmp, "reset") == 0) instr = QANSEL_INSTRUCTION_RESET; + else if (strcmp(tmp, "print") == 0) instr = QANSEL_INSTRUCTION_PRINT; + } + { + int strbeg = regmatches[rmp].rm_so; + int strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so; + rmp++; + if (strlen > 0) + { + strbeg = regmatches[rmp].rm_so; + strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so; + rmp++; + char tmp[strlen + 1]; + memcpy(tmp, chunk + strbeg, strlen); + tmp[strlen] = 0; + a0 = atoi(tmp); + if (a0 >= *bitCount) + { + fprintf(stderr, "QAnsel on line %i: Index `%i` exceeds allocated classical bits.\n", line, a0); + return 0; + } + a0 += 0x10; } else { - fprintf(stderr, "QAnsel: Syntax error"); - errFound = 1; - break; - } - if (qubitCount == 0xFF) - { - fprintf(stderr, "QAnsel: Instruction before initialization"); - errFound = 1; - break; - } - if (q0 < 0 || q0 >= qubitCount) - { - fprintf(stderr, "QAnsel: Invalid index"); - errFound = 1; - break; - } - - instr = realloc(instr, (instrLen + 1) * sizeof(QInstr)); - instr[instrLen].n[0] = 'u'; - instr[instrLen].n[1] = 0; - instr[instrLen].q0 = q0; - switch (ty) - { - case 'x': - instr[instrLen].arg0 = M_PI / 2; - instr[instrLen].arg1 = -M_PI / 2; - instr[instrLen].arg2 = angle - (M_PI / 2); - break; - case 'y': - instr[instrLen].arg0 = angle; - instr[instrLen].arg1 = 0; - instr[instrLen].arg2 = 0; - break; - case 'z': - instr[instrLen].arg0 = 0; - instr[instrLen].arg1 = 0; - instr[instrLen].arg2 = angle; - break; - } - instrLen++; - } - else if (sscanf(lines[i], "density q[%i]%n", &q0, &matchedCount) == 1) - { - g = lines[i][0]; - if (qubitCount == 0xFF) - { - fprintf(stderr, "QAnsel: Instruction before initialization"); - errFound = 1; - break; - } - if (q0 < 0 || q0 >= qubitCount) - { - fprintf(stderr, "QAnsel: Invalid index"); - errFound = 1; - break; - } - instr = realloc(instr, (instrLen + 1) * sizeof(QInstr)); - strcpy(instr[instrLen].n, "density"); - instr[instrLen++].q0 = (unsigned char)q0; - } - else if - ( - sscanf(lines[i], "h q[%i]%n", &q0, &matchedCount) == 1 - || sscanf(lines[i], "x q[%i]%n", &q0, &matchedCount) == 1 - || sscanf(lines[i], "y q[%i]%n", &q0, &matchedCount) == 1 - || sscanf(lines[i], "z q[%i]%n", &q0, &matchedCount) == 1 - || sscanf(lines[i], "t q[%i]%n", &q0, &matchedCount) == 1 - || sscanf(lines[i], "s q[%i]%n", &q0, &matchedCount) == 1 - ) - { - g = lines[i][0]; - if (qubitCount == 0xFF) - { - fprintf(stderr, "QAnsel: Instruction before initialization"); - errFound = 1; - break; - } - if (q0 < 0 || q0 >= qubitCount) - { - fprintf(stderr, "QAnsel: Invalid index"); - errFound = 1; - break; - } - instr = realloc(instr, (instrLen + 1) * sizeof(QInstr)); - instr[instrLen].n[0] = g; - instr[instrLen].n[1] = 0; - instr[instrLen++].q0 = (unsigned char)q0; - } - else if (sscanf(lines[i], "cx q[%i], q[%i]%n", &q0, &q1, &matchedCount) == 2) - { - if (qubitCount == 0xFF) - { - fprintf(stderr, "QAnsel: Instruction before initialization"); - errFound = 1; - break; - } - if (q0 >= qubitCount || q1 >= qubitCount | q0 < 0 || q1 < 0 || q0 == q1) - { - fprintf(stderr, "QAnsel: Invalid index"); - errFound = 1; - break; - } - instr = realloc(instr, (instrLen + 1) * sizeof(QInstr)); - strcpy(instr[instrLen].n, "cx"); - instr[instrLen].q0 = q0; - instr[instrLen++].q1 = q1; - } - else if (sscanf(lines[i], "swap q[%i], q[%i]%n", &q0, &q1, &matchedCount) == 2) - { - if (qubitCount == 0xFF) - { - fprintf(stderr, "QAnsel: Instruction before initialization"); - errFound = 1; - break; - } - if (q0 >= qubitCount || q1 >= qubitCount | q0 < 0 || q1 < 0 || q0 == q1) - { - fprintf(stderr, "QAnsel: Invalid index"); - errFound = 1; - break; - } - instr = realloc(instr, (instrLen + 1) * sizeof(QInstr)); - strcpy(instr[instrLen].n, "swap"); - instr[instrLen].q0 = q0; - instr[instrLen++].q1 = q1; - } - else if - ( - sscanf(lines[i], "cswap q[%i], q[%i], q[%i]%n", &q0, &q1, &q2, &matchedCount) == 3 - || sscanf(lines[i], "fredkin q[%i], q[%i], q[%i]%n", &q0, &q1, &q2, &matchedCount) == 3 - ) - { - if (qubitCount == 0xFF) - { - fprintf(stderr, "QAnsel: Instruction before initialization"); - errFound = 1; - break; - } - if (qubitCount < 3) - { - fprintf(stderr, "QAnsel: Three qubit gate used with insufficient qubits initialized"); - errFound = 1; - break; - } - if (q0 >= qubitCount || q1 >= qubitCount || q2 >= qubitCount || q0 < 0 || q1< 0 || q2 < 0 || q0 == q1 || q1 == q2 || q0 == q2) - { - fprintf(stderr, "QAnsel: Invalid index"); - errFound = 1; - break; + a0 = 0x1F; } - instr = realloc(instr, (instrLen + 1) * sizeof(QInstr)); - strcpy(instr[instrLen].n, "cswap"); - instr[instrLen].q0 = q0; - instr[instrLen].q1 = q1; - instr[instrLen++].q2 = q2; } - else if - ( - sscanf(lines[i], "ccx q[%i], q[%i], q[%i]%n", &q0, &q1, &q2, &matchedCount) == 3 - || sscanf(lines[i], "toffoli q[%i], q[%i], q[%i]%n", &q0, &q1, &q2, &matchedCount) == 3 - ) - { - if (qubitCount == 0xFF) - { - fprintf(stderr, "QAnsel: Instruction before initialization"); - errFound = 1; - break; - } - if (qubitCount < 3) - { - fprintf(stderr, "QAnsel: Three qubit gate used with insufficient qubits initialized"); - errFound = 1; - break; - } - if (q0 >= qubitCount || q1 >= qubitCount || q2 >= qubitCount || q0 < 0 || q1< 0 || q2 < 0 || q0 == q1 || q1 == q2 || q0 == q2) - { - fprintf(stderr, "QAnsel: Invalid index"); - errFound = 1; - break; - } - instr = realloc(instr, (instrLen + 1) * sizeof(QInstr)); - strcpy(instr[instrLen].n, "ccx"); - instr[instrLen].q0 = q0; - instr[instrLen].q1 = q1; - instr[instrLen++].q2 = q2; - } - else if (sscanf(lines[i], "measure q[%i] -> c[%i]%n", &q0, &q1, &matchedCount) == 2) - { - if (bitCount == 0xFF) - { - fprintf(stderr, "QAnsel: Measure instruction used before bit initialization"); - errFound = 1; - break; - } - if (q0 >= qubitCount || q1 >= bitCount || q0 < 0 || q1 < 0) - { - fprintf(stderr, "QAnsel: Invalid index"); - errFound = 1; - break; - } - instr = realloc(instr, (instrLen + 1) * sizeof(QInstr)); - strcpy(instr[instrLen].n, "measure"); - instr[instrLen].q0 = q0; - instr[instrLen++].q1 = q1; - } - else if (sscanf(lines[i], "if(c==%i)%n", &q0, &matchedCount) == 1) - { - if (bitCount == 0xFF) - { - fprintf(stderr, "QAnsel: If instruction used before bit initialization"); - errFound = 1; - break; - } - if (q0 < 0) - { - fprintf(stderr, "QAnsel: Invalid comparison"); - errFound = 1; - break; - } - instr = realloc(instr, (instrLen + 1) * sizeof(QInstr)); - strcpy(instr[instrLen].n, "if_all"); - instr[instrLen++].q0 = q0; - } - else if (sscanf(lines[i], "if(c[%i]==%i)%n", &q0, &q1, &matchedCount) == 2) - { - if (bitCount == 0xFF) - { - fprintf(stderr, "QAnsel: If instruction used before bit initialization"); - errFound = 1; - break; - } - if (q0 < 0 || q1 < 0 || q0 > bitCount) - { - fprintf(stderr, "QAnsel: Invalid comparison"); - errFound = 1; - break; - } - instr = realloc(instr, (instrLen + 1) * sizeof(QInstr)); - strcpy(instr[instrLen].n, "if"); - instr[instrLen].q0 = q0; - instr[instrLen++].q1 = q1; - } - /*else if (strcmp(lines[i], "display") == 0) - { - if (doDisplay) - { - fprintf(stderr, "QAnsel: Display re-initialized"); - errFound = 1; - break; - } - doDisplay = 1; - }*/ - else if (strcmp(lines[i], "print q") == 0) - { - matchedCount = lineLen; - if (qubitCount == 0xFF) - { - fprintf(stderr, "QAnsel: Qubit instruction used before initialization"); - errFound = 1; - break; - } - instr = realloc(instr, (instrLen + 1) * sizeof(QInstr)); - strcpy(instr[instrLen].n, "printq_all"); - instrLen++; - } - else if (strcmp(lines[i], "print c") == 0) - { - matchedCount = lineLen; - if (bitCount == 0xFF) - { - fprintf(stderr, "QAnsel: Bit instruction used before initialization"); - errFound = 1; - break; - } - instr = realloc(instr, (instrLen + 1) * sizeof(QInstr)); - strcpy(instr[instrLen].n, "printc_all"); - instrLen++; - } - else if (sscanf(lines[i], "print q[%i]%n", &q0, &matchedCount) == 1) - { - if (qubitCount == 0xFF) - { - fprintf(stderr, "QAnsel: Qubit instruction used before initialization"); - errFound = 1; - break; - } - if (q0 >= qubitCount || q0 < 0) - { - fprintf(stderr, "QAnsel: Invalid index"); - errFound = 1; - break; - } - instr = realloc(instr, (instrLen + 1) * sizeof(QInstr)); - strcpy(instr[instrLen].n, "printq"); - instr[instrLen++].q0 = q0; - } - else if (sscanf(lines[i], "print c[%i]%n", &q0, &matchedCount) == 1) - { - if (bitCount == 0xFF) - { - fprintf(stderr, "QAnsel: Bit instruction used before initialization"); - errFound = 1; - break; - } - if (q0 >= bitCount || q0 < 0) - { - fprintf(stderr, "QAnsel: Invalid index"); - errFound = 1; - break; - } - instr = realloc(instr, (instrLen + 1) * sizeof(QInstr)); - strcpy(instr[instrLen].n, "printc"); - instr[instrLen++].q0 = q0; - } - else if (strcmp(lines[i], "born") == 0 || strcmp(lines[i], "born q") == 0) - { - matchedCount = lineLen; - if (qubitCount == 0xFF) - { - fprintf(stderr, "QAnsel: Qubit instruction used before initialization"); - errFound = 1; - break; - } - instr = realloc(instr, (instrLen + 1) * sizeof(QInstr)); - strcpy(instr[instrLen].n, "born_all"); - instrLen++; - } - else if (sscanf(lines[i], "born q[%i]%n", &q0, &matchedCount) == 1) - { - if (qubitCount == 0xFF) - { - fprintf(stderr, "QAnsel: Qubit instruction used before initialization"); - errFound = 1; - break; - } - if (q0 >= qubitCount || q0 < 0) - { - fprintf(stderr, "QAnsel: Invalid index"); - errFound = 1; - break; - } - instr = realloc(instr, (instrLen + 1) * sizeof(QInstr)); - strcpy(instr[instrLen].n, "born"); - instr[instrLen++].q0 = q0; - } - else if (sscanf(lines[i], "reset q[%i]%n", &q0, &matchedCount) == 1) - { - if (qubitCount == 0xFF) - { - fprintf(stderr, "QAnsel: Qubit instruction used before initialization"); - errFound = 1; - break; - } - if (q0 >= qubitCount || q0 < 0) - { - fprintf(stderr, "QAnsel: Invalid index"); - errFound = 1; - break; - } - instr = realloc(instr, (instrLen + 1) * sizeof(QInstr)); - strcpy(instr[instrLen].n, "resetq"); - instr[instrLen++].q0 = q0; - } - else if (sscanf(lines[i], "reset c[%i]%n", &q0, &matchedCount) == 1) - { - if (bitCount == 0xFF) - { - fprintf(stderr, "QAnsel: Bit instruction used before initialization"); - errFound = 1; - break; - } - if (q0 >= bitCount || q0 < 0) - { - fprintf(stderr, "QAnsel: Invalid index"); - errFound = 1; - break; - } - instr = realloc(instr, (instrLen + 1) * sizeof(QInstr)); - strcpy(instr[instrLen].n, "resetc"); - instr[instrLen++].q0 = q0; - } - else if (strcmp(lines[i], "reset") == 0) + *binarySize += 2; + binary = realloc(binary, *binarySize); + binary[*binarySize - 2] = instr; + binary[*binarySize - 1] = a0; + } + else if (index == 8 || index == 9) //double qubit instructions + { + if (*qubitCount == 0) { - matchedCount = lineLen; - instr = realloc(instr, (instrLen + 1) * sizeof(QInstr)); - strcpy(instr[instrLen].n, "reset_all"); - instrLen++; + fprintf(stderr, "QAnsel on line %i: Quantum bit instruction used prior to initialization.\n", line); + return 0; } - else if (strcmp(lines[i], "barrier q") == 0) + int rmp = 1; { - matchedCount = lineLen; - if (qubitCount == 0xFF) - { - fprintf(stderr, "QAnsel: Qubit instruction used before initialization"); - errFound = 1; - break; - } - //do nothing as there are currently no - // optimizations that this instruction - // would prevent + int strbeg = regmatches[rmp].rm_so; + int strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so; + rmp++; + char tmp[strlen + 1]; + memcpy(tmp, chunk + strbeg, strlen); + tmp[strlen] = 0; + if (strcmp(tmp, "cx") == 0) instr = QANSEL_INSTRUCTION_CX; + if (strcmp(tmp, "cnot") == 0) instr = QANSEL_INSTRUCTION_CCX; + else if (strcmp(tmp, "toffoli") == 0) instr = QANSEL_INSTRUCTION_CCX; + else if (strcmp(tmp, "cswap") == 0) instr = QANSEL_INSTRUCTION_CSWAP; + else if (strcmp(tmp, "fredkin") == 0) instr = QANSEL_INSTRUCTION_CSWAP; } - else if (sscanf(lines[i], "barrier q[%i]%n", &q0, &matchedCount) == 1) + for (int i = 0; i < (index == 8 ? 2 : 3); i++) { - if (qubitCount == 0xFF || bitCount == 0xFF) + int strbeg = regmatches[rmp].rm_so; + int strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so; + rmp++; + char tmp[strlen + 1]; + memcpy(tmp, chunk + strbeg, strlen); + tmp[strlen] = 0; + int tmpi = atoi(tmp); + if (tmpi >= *qubitCount) { - fprintf(stderr, "QAnsel: Instruction used before initialization"); - errFound = 1; - break; + fprintf(stderr, "QAnsel on line %i: Index `%i` exceeds allocated quantum bits.\n", line, tmpi); + return 0; } - if (q0 >= qubitCount || q0 < 0) + switch (i) { - fprintf(stderr, "QAnsel: Invalid index"); - errFound = 1; - break; + case 0: a0 = tmpi; break; + case 1: a1 = tmpi; break; + case 2: a2 = tmpi; break; } - //do nothing as there are currently no - // optimizations that this instruction - // would prevent - } - else if (sscanf(lines[i], "hvar %f%n", &a0, &matchedCount) == 1) - { - instr = realloc(instr, (instrLen + 1) * sizeof(QInstr)); - strcpy(instr[instrLen].n, "hvar"); - instr[instrLen++].arg0 = a0; - } - else if (strcmp(lines[i], "rand") == 0) - { - matchedCount = lineLen; - instr = realloc(instr, (instrLen + 1) * sizeof(QInstr)); - strcpy(instr[instrLen].n, "rand"); - instrLen++; } - else if (strcmp(lines[i], "sample") == 0 || strcmp(lines[i], "sample c") == 0) + if (index == 8) { - matchedCount = lineLen; - if (i != linesLen - 1) - { - fprintf(stderr, "QAnsel: Sampling should be performed at the end of the program;"); - errFound = 1; - break; - } - if (bitCount == 0xFF) - { - fprintf(stderr, "QAnsel: Sampling cannot be used without initializing classical bits; "); - errFound = 1; - break; - } - fullSample = 255; - } - else if (sscanf(lines[i], "sample c[%i]%n", &q0, &matchedCount) == 1) - { - if (i != linesLen - 1) - { - fprintf(stderr, "QAnsel: Sampling should be performed at the end of the program;"); - errFound = 1; - break; - } - if (bitCount == 0xFF) - { - fprintf(stderr, "QAnsel: Sampling cannot be used without initializing classical bits; "); - errFound = 1; - break; - } - fullSample = q0 + 1; + *binarySize += 3; + binary = realloc(binary, *binarySize); + binary[*binarySize - 3] = instr; + binary[*binarySize - 2] = a0; + binary[*binarySize - 1] = a1; } else { - fprintf(stderr, "QAnsel: Syntax error"); - errFound = 1; - break; + *binarySize += 4; + binary = realloc(binary, *binarySize); + binary[*binarySize - 4] = instr; + binary[*binarySize - 3] = a0; + binary[*binarySize - 2] = a1; + binary[*binarySize - 1] = a2; } - if (lineLen != matchedCount) - { - fprintf(stderr, "QAnsel: Invalid trailing text"); - errFound = 1; - break; - } - } - - for (unsigned int i = 0; i < linesLen; i++) free(lines[i]); - free(lines); - - if (errFound) + else if (index == 10) //if instructions { - printf(" on line %i.\n", lineIDs[lineID]); - free(lineIDs); - free(instr); - exit(1); + if (*bitCount == 0) + { + fprintf(stderr, "QAnsel on line %i: Classical bit instruction used prior to initialization.\n", line); + return 0; + } + int rmp = 1; + { + int strbeg = regmatches[rmp].rm_so; + int strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so; + rmp++; + if (strlen > 0) + { + strbeg = regmatches[rmp].rm_so; + strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so; + rmp++; + char tmp[strlen + 1]; + memcpy(tmp, chunk + strbeg, strlen); + tmp[strlen] = 0; + a0 = atoi(tmp); + if (a0 >= *bitCount) + { + fprintf(stderr, "QAnsel on line %i: Index `%i` exceeds allocated classical bits.\n", line, a0); + return 0; + } + a0 += 0x10; + } + else + { + a0 = 0x1F; + } + } + { + int strbeg = regmatches[rmp].rm_so; + int strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so; + rmp++; + char tmp[strlen + 1]; + memcpy(tmp, chunk + strbeg, strlen); + tmp[strlen] = 0; + if (strcmp(tmp, "==") == 0) instr = QANSEL_INSTRUCTION_IF_E; + else if (strcmp(tmp, "!=") == 0) instr = QANSEL_INSTRUCTION_IF_NE; + else if (strcmp(tmp, "<>") == 0) instr = QANSEL_INSTRUCTION_IF_NE; + else if (strcmp(tmp, ">=") == 0) instr = QANSEL_INSTRUCTION_IF_GE; + else if (strcmp(tmp, "<=") == 0) instr = QANSEL_INSTRUCTION_IF_LE; + else if (strcmp(tmp, ">") == 0) instr = QANSEL_INSTRUCTION_IF_G; + else if (strcmp(tmp, "<") == 0) instr = QANSEL_INSTRUCTION_IF_L; + } + { + int strbeg = regmatches[rmp].rm_so; + int strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so; + rmp++; + char tmp[strlen + 1]; + memcpy(tmp, chunk + strbeg, strlen); + tmp[strlen] = 0; + s0 = (unsigned short)atoi(tmp); + } + *binarySize += 2 + sizeof(unsigned short); + binary = realloc(binary, *binarySize); + binary[*binarySize - 2 - sizeof(unsigned short)] = instr; + binary[*binarySize - 1 - sizeof(unsigned short)] = a0; + memcpy(binary + (*binarySize - sizeof(unsigned short)), &s0, sizeof(unsigned short)); } - - if (argc == 2) + else if (index == 11) //floating point settings { - if (strcmp(argv[1], "-d") == 0) + int rmp = 1; { - doDisplay = 1; + int strbeg = regmatches[rmp].rm_so; + int strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so; + rmp++; + char tmp[strlen + 1]; + memcpy(tmp, chunk + strbeg, strlen); + tmp[strlen] = 0; + if (strcmp(tmp, "hvar") == 0) instr = QANSEL_INSTRUCTION_HVAR; } - } - else if (argc == 3) - { - if (strcmp(argv[1], "-h") == 0) { - seed = atof(argv[2]); - qansel_rand_s(seed); + int strbeg = regmatches[rmp].rm_so; + int strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so; + rmp++; + char tmp[strlen + 1]; + memcpy(tmp, chunk + strbeg, strlen); + tmp[strlen] = 0; + if (!qansel_parse_float(tmp, &d0)) + { + fprintf(stderr, "QAnsel on line %i: Syntax error.\n", line); + return 0; + } } + *binarySize += 1 + sizeof(float); + binary = realloc(binary, *binarySize); + binary[*binarySize - 1 - sizeof(float)] = instr; + memcpy(binary + (*binarySize - sizeof(float)), &d0, sizeof(float)); } - else if (argc == 4) + else if (index == 12) //lone instructions { - if (strcmp(argv[1], "-d") == 0) - { - doDisplay = 1; - } - else if (strcmp(argv[3], "-d") == 0) - { - doDisplay = 1; - } - if (strcmp(argv[1], "-h") == 0) - { - seed = atof(argv[2]); - qansel_rand_s(seed); - } - else if (strcmp(argv[2], "-h") == 0) - { - seed = atof(argv[3]); - qansel_rand_s(seed); - } + int rmp = 1; + { + int strbeg = regmatches[rmp].rm_so; + int strlen = regmatches[rmp].rm_eo - regmatches[rmp].rm_so; + rmp++; + char tmp[strlen + 1]; + memcpy(tmp, chunk + strbeg, strlen); + tmp[strlen] = 0; + if (strcmp(tmp, "rand") == 0) instr = QANSEL_INSTRUCTION_RAND; + else if (strcmp(tmp, "exit") == 0) instr = QANSEL_INSTRUCTION_EXIT; + } + *binarySize += 1; + binary = realloc(binary, *binarySize); + binary[*binarySize - 1] = instr; } + return 1; +} - if (fullSample) +int qansel_process_chunks(char** chunks, int* associatedLines, int count) +{ + unsigned char* binary = malloc(0); + int binarySize = 0; + int qubitCount = 0; + int bitCount = 0; + char errbuf[100]; + regex_t regex; + regmatch_t regmatches[10]; + const char regexes[][1024] = { - unsigned short stats[65536]; - for (unsigned int i = 0; i < (1 << bitCount); i++) - { - stats[i] = 0; - } - unsigned char bitVect[bitCount]; - for (int i = 0; i < bitCount; i++) bitVect[i] = 0; - - unsigned char* dat = malloc(instrLen * sizeof(QInstr)); - memcpy(dat, instr, instrLen * sizeof(QInstr)); - unsigned int shots = 1000; - for (unsigned int i = 0; i < shots; i++) + "^\\s*qreg\\s*q\\s*\\[\\s*([0-9][0-9]*)\\s*\\]\\s*$", + "^\\s*creg\\s*c\\s*\\[\\s*([0-9][0-9]*)\\s*\\]\\s*$", + "^\\s*(x|y|z|h|s|t|reset|barrier|born|density|print)\\s*q\\s*(\\[\\s*([0-9][0-9]*)\\s*\\]\\s*|)$", + "^\\s*(rx|ry|rz|u1)\\(\\s*([-/0-9PI.]*)\\s*\\)\\s*q\\s*(\\[\\s*([0-9][0-9]*)\\s*\\]\\s*|)$", + "^\\s*(u2)\\(\\s*([-/0-9PI.]*)\\s*,\\s*([-/0-9PI.]*)\\s*\\)\\s*q\\s*(\\[\\s*([0-9][0-9]*)\\s*\\]\\s*|)$", + "^\\s*(u|u3)\\(\\s*([-/0-9PI.]*)\\s*,\\s*([-/0-9PI.]*)\\s*,\\s*([-/0-9PI.]*)\\s*\\)\\s*q\\s*(\\[\\s*([0-9][0-9]*)\\s*\\]\\s*|)$", + "^\\s*measure\\s*q\\s*(\\[\\s*([0-9]*)\\s*\\]\\s*|)\\s*->\\s*c\\c*(\\[\\s*([0-9][0-9]*)\\s*\\]\\s*|)$", + "^\\s*(sample|reset|print)\\s*c\\s*(\\[\\s*([0-9][0-9]*)\\s*\\]\\s*|)$", + "^\\s*(cx|cnot|swap)\\s*q\\s*\\[\\s*([0-9][0-9]*)\\s*\\]\\s*,\\s*q\\s*\\[\\s*([0-9]*)\\s*\\]\\s*$", + "^\\s*(ccx|toffoli|cswap|fredkin)\\s*q\\s*\\[\\s*([0-9]*)\\s*\\]\\s*,\\s*q\\s*\\[\\s*([0-9]*)\\s*\\]\\s*,\\s*q\\s*\\[\\s*([0-9][0-9]*)\\s*\\]\\s*$", + "^\\s*if\\s*\\(\\s*c\\s*(\\[\\s*([0-9][0-9]*)\\s*\\]|)\\s*(==|!=|<>|>=|<=|>|<)\\s*([0-9][0-9]*)\\s*\\).*\\s*$", + "^\\s*(hvar)\\s*([-/0-9PI.]*)\\s*$", + "^\\s*(rand|exit)\\s*$", + }; + int ret, status, found; + for (int i = 0; i < count; i++) + { + found = 0; + for (int j = 0; j < sizeof(regexes) / sizeof(regexes[0]); j++) { - qansel_run(qubitCount, bitCount, instr, bitVect, instrLen, doDisplay); - memcpy(instr, dat, instrLen * sizeof(QInstr)); - unsigned short stat = 0; - for (signed char j = bitCount - 1; j >= 0; j--) + if (regcomp(®ex, regexes[j], REG_EXTENDED | REG_ICASE)) { - stat = (stat << 1) | bitVect[j]; + printf("QAnsel: Regex fatal error.\n"); + exit(1); } - stats[stat]++; - } - free(dat); - unsigned int count = 0; - for (unsigned int i = 0; i < (1 << bitCount); i++) - { - unsigned int tmp = i; - for (unsigned char j = 0; j < bitCount; j++) + ret = regexec(®ex, chunks[i], 10, regmatches, 0); + if (!ret) { - unsigned char bit = (tmp >> (bitCount - 1) & 1); - if (j == (bitCount - (fullSample - 1) - 1) && bit) - { - count += stats[i]; - } - if (fullSample == 255) - { - putchar('0' + bit); - } - tmp <<= 1; + found = 1; + status = qansel_process_chunk(j, chunks[i], associatedLines[i], regmatches, &qubitCount, &bitCount, binary, &binarySize); + break; } - if (fullSample == 255) + else if (ret == REG_NOMATCH) {} + else { - printf(": %.1f%%\n", ((float)stats[i] / (float)shots) * (float)100); + regerror(ret, ®ex, errbuf, sizeof(errbuf)); + fprintf(stderr, "QAnsel: %s.\n", errbuf); + exit(1); } + regfree(®ex); } - if (fullSample != 255) - { - float prob = ((float)count / (float)shots) * (float)100; - printf("0: %.1f%%\n", ((float)100)-prob); - printf("1: %.1f%%\n", prob); + if (!status) break; + if (!found) + { + fprintf(stderr, "QAnsel on line %i: Invalid syntax.\n", associatedLines[i]); + return 0; } } - else - { - qansel_run(qubitCount, bitCount, instr, NULL, instrLen, doDisplay); - } - free(instr); - free(lineIDs); + qansel_execute(binary, binarySize); } void main(int argc, char** argv) { - MODE = MODE_METAL_THREADED; + char* script = malloc(0); + size_t scriptSize = 0; + int c; + while ( (c = getchar()) != EOF ) + { + script = realloc(script, scriptSize + 1); + script[scriptSize++] = c; + } + script = realloc(script, scriptSize + 1); + script[scriptSize++] = 0; + + char** chunks; + int* chunksAssociatedLines; + int chunksCount; + qansel_read_script(script, &chunks, &chunksAssociatedLines, &chunksCount); + qansel_process_chunks(chunks, chunksAssociatedLines, chunksCount); + for (int i = 0; i < chunksCount; i++) free(chunks[i]); + free(chunks); + free(chunksAssociatedLines); + free(script); + return; + + MODE = MODE_BARE; unsigned char err = cpx_mtx_begin(); if (err == 0 && (MODE == MODE_METAL_THREADED || MODE == MODE_METAL)) { @@ -1430,7 +743,7 @@ void main(int argc, char** argv) } RANDOM_FILE = fopen("/dev/TrueRNG0", "r"); if (!RANDOM_FILE) RANDOM_FILE = fopen("/dev/random", "r"); - process(argc, argv); + //qansel_execute fclose(RANDOM_FILE); if (MODE_METAL || MODE_METAL_THREADED) cpx_mtx_clean(); } \ No newline at end of file diff --git a/src/core.c b/src/core.c new file mode 100644 index 0000000..46c940f --- /dev/null +++ b/src/core.c @@ -0,0 +1,1103 @@ +#include +#include +#include +#include +#include "complex.c" +#include "gates.c" +#include "display.c" +#include "chacha20.c" +#define QUBITS_MAX 14 +unsigned char HIDDEN_VARIABLE = 0; +FILE* RANDOM_FILE; +#define GPU_ENABLED +unsigned char USE_THREADS = 1; +#define MODE_BARE 1 +#define MODE_THREADED 2 +#define MODE_METAL 3 +#define MODE_METAL_THREADED 4 +unsigned char MODE = MODE_BARE; +//#define SPEED_TEST + +#define QANSEL_INSTRUCTION_X 0x10 +#define QANSEL_INSTRUCTION_Y 0x11 +#define QANSEL_INSTRUCTION_Z 0x12 +#define QANSEL_INSTRUCTION_H 0x13 +#define QANSEL_INSTRUCTION_S 0x14 +#define QANSEL_INSTRUCTION_T 0x15 +#define QANSEL_INSTRUCTION_RX 0x20 +#define QANSEL_INSTRUCTION_RY 0x21 +#define QANSEL_INSTRUCTION_RZ 0x22 +#define QANSEL_INSTRUCTION_U1 0x23 +#define QANSEL_INSTRUCTION_U2 0x24 +#define QANSEL_INSTRUCTION_U3 0x25 +#define QANSEL_INSTRUCTION_CX 0x30 +#define QANSEL_INSTRUCTION_SWAP 0x31 +#define QANSEL_INSTRUCTION_CCX 0x40 +#define QANSEL_INSTRUCTION_CSWAP 0x41 +#define QANSEL_INSTRUCTION_MEASURE 0xD0 +#define QANSEL_INSTRUCTION_SAMPLE 0xD1 +#define QANSEL_INSTRUCTION_DENSITY 0xD2 +#define QANSEL_INSTRUCTION_BORN 0xD3 +#define QANSEL_INSTRUCTION_IF_E 0xE1 +#define QANSEL_INSTRUCTION_IF_NE 0xE2 +#define QANSEL_INSTRUCTION_IF_G 0xE3 +#define QANSEL_INSTRUCTION_IF_GE 0xE4 +#define QANSEL_INSTRUCTION_IF_L 0xE5 +#define QANSEL_INSTRUCTION_IF_LE 0xE6 +#define QANSEL_INSTRUCTION_RAND 0xF0 +#define QANSEL_INSTRUCTION_HVAR 0xF1 +#define QANSEL_INSTRUCTION_RESET 0xF2 +#define QANSEL_INSTRUCTION_PRINT 0xF3 +#define QANSEL_INSTRUCTION_BARRIER 0xF4 +#define QANSEL_INSTRUCTION_EXIT 0xF5 + +#define QANSEL_FLAGS_EQUAL 0b00001 +#define QANSEL_FLAGS_GREATER 0b00010 +#define QANSEL_FLAGS_LESSER 0b00100 +#define QANSEL_FLAGS_JUMPED 0b01000 +typedef struct +{ + char n[128]; + unsigned char q0, q1, q2; + float arg0, arg1, arg2; +} QInstr; + +const char* qansel_instruction_to_string(unsigned char instr) +{ + switch (instr) + { + case QANSEL_INSTRUCTION_X: return "QANSEL_INSTRUCTION_X"; + case QANSEL_INSTRUCTION_Y: return "QANSEL_INSTRUCTION_Y"; + case QANSEL_INSTRUCTION_Z: return "QANSEL_INSTRUCTION_Z"; + case QANSEL_INSTRUCTION_H: return "QANSEL_INSTRUCTION_H"; + case QANSEL_INSTRUCTION_S: return "QANSEL_INSTRUCTION_S"; + case QANSEL_INSTRUCTION_T: return "QANSEL_INSTRUCTION_T"; + case QANSEL_INSTRUCTION_RX: return "QANSEL_INSTRUCTION_RX"; + case QANSEL_INSTRUCTION_RY: return "QANSEL_INSTRUCTION_RY"; + case QANSEL_INSTRUCTION_RZ: return "QANSEL_INSTRUCTION_RZ"; + case QANSEL_INSTRUCTION_U1: return "QANSEL_INSTRUCTION_U1"; + case QANSEL_INSTRUCTION_U2: return "QANSEL_INSTRUCTION_U2"; + case QANSEL_INSTRUCTION_U3: return "QANSEL_INSTRUCTION_U3"; + case QANSEL_INSTRUCTION_CX: return "QANSEL_INSTRUCTION_CX"; + case QANSEL_INSTRUCTION_SWAP: return "QANSEL_INSTRUCTION_SWAP"; + case QANSEL_INSTRUCTION_CCX: return "QANSEL_INSTRUCTION_CCX"; + case QANSEL_INSTRUCTION_CSWAP: return "QANSEL_INSTRUCTION_CSWAP"; + case QANSEL_INSTRUCTION_MEASURE: return "QANSEL_INSTRUCTION_MEASURE"; + case QANSEL_INSTRUCTION_SAMPLE: return "QANSEL_INSTRUCTION_SAMPLE"; + case QANSEL_INSTRUCTION_DENSITY: return "QANSEL_INSTRUCTION_DENSITY"; + case QANSEL_INSTRUCTION_BORN: return "QANSEL_INSTRUCTION_BORN"; + case QANSEL_INSTRUCTION_IF_E: return "QANSEL_INSTRUCTION_JUMP_E"; + case QANSEL_INSTRUCTION_IF_NE: return "QANSEL_INSTRUCTION_JUMP_NE"; + case QANSEL_INSTRUCTION_IF_G: return "QANSEL_INSTRUCTION_JUMP_G"; + case QANSEL_INSTRUCTION_IF_GE: return "QANSEL_INSTRUCTION_JUMP_GE"; + case QANSEL_INSTRUCTION_IF_L: return "QANSEL_INSTRUCTION_JUMP_L"; + case QANSEL_INSTRUCTION_IF_LE: return "QANSEL_INSTRUCTION_JUMP_LE"; + case QANSEL_INSTRUCTION_RAND: return "QANSEL_INSTRUCTION_RAND"; + case QANSEL_INSTRUCTION_HVAR: return "QANSEL_INSTRUCTION_HVAR"; + case QANSEL_INSTRUCTION_RESET: return "QANSEL_INSTRUCTION_RESET"; + case QANSEL_INSTRUCTION_PRINT: return "QANSEL_INSTRUCTION_PRINT"; + case QANSEL_INSTRUCTION_BARRIER: return "QANSEL_INSTRUCTION_BARRIER"; + case QANSEL_INSTRUCTION_EXIT: return "QANSEL_INSTRUCTION_EXIT"; + } + return "Unknown"; +} +float qansel_rand_s(float s) +{ + unsigned int tmp; + memcpy(&tmp, &s, sizeof(unsigned int)); + srand(tmp); +} +float qansel_rand_h() +{ + return ((float)rand()) / ((float)RAND_MAX); +} +float qansel_rand_t() +{ + if (RANDOM_FILE) + { + unsigned int num = 0; + for (unsigned char i = 0; i < 4; i++) + { + num = (num << 8) | fgetc(RANDOM_FILE); + } + return ((float)num) / ((float)UINT32_MAX); + } + else + { + HIDDEN_VARIABLE = 1; + return qansel_rand_h(); + } +} + +float qansel_rand() +{ + return HIDDEN_VARIABLE ? qansel_rand_h() : qansel_rand_t(); +} + +void qansel_cnot(cpx_mtx_t* stateVector, unsigned char qubitCount, unsigned char bitA, unsigned char bitB) +{ + if (bitA >= qubitCount || bitB >= qubitCount) return; + unsigned int retLen = (unsigned int)pow(2, qubitCount); + cpx_mtx_t ret; + cpx_mtx_init(&ret, 1, retLen); + cpx_t n; + for (unsigned int i = 0; i < retLen; i++) + { + unsigned char bitAVal = (i >> bitA) & 1; + unsigned char bitBVal = (i >> bitB) & 1; + unsigned char bitBNew = bitAVal ? !bitBVal : bitBVal; + unsigned int j = (i & ~(1 << bitB)) | (bitBNew << bitB); + cpx_mtx_get(stateVector, 0, i, &n); + cpx_mtx_set(&ret, 0, j, &n); + } + cpx_mtx_free(stateVector); + stateVector->ptr = ret.ptr; + stateVector->rows = ret.rows; + stateVector->cols = ret.cols; +} + +void qansel_swap(cpx_mtx_t* stateVector, unsigned char qubitCount, unsigned char bitA, unsigned char bitB) +{ + if (bitA >= qubitCount || bitB >= qubitCount) return; + unsigned int retLen = (unsigned int)pow(2, qubitCount); + cpx_mtx_t ret; + cpx_mtx_init(&ret, 1, retLen); + cpx_t n; + for (unsigned int i = 0; i < retLen; i++) + { + unsigned char bitAVal = (i >> bitA) & 1; + unsigned char bitBVal = (i >> bitB) & 1; + unsigned char bitANew = bitBVal; + unsigned char bitBNew = bitAVal; + unsigned int j = (i & ~((1 << bitA) | (1 << bitB))) | ((bitANew << bitA) | (bitBNew << bitB)); + cpx_mtx_get(stateVector, 0, i, &n); + cpx_mtx_set(&ret, 0, j, &n); + } + cpx_mtx_free(stateVector); + stateVector->ptr = ret.ptr; + stateVector->rows = ret.rows; + stateVector->cols = ret.cols; +} + +void qansel_fredkin(cpx_mtx_t* stateVector, unsigned char qubitCount, unsigned char bitA, unsigned char bitB, unsigned char bitC) +{ + if (bitA >= qubitCount || bitB >= qubitCount) return; + unsigned int retLen = (unsigned int)pow(2, qubitCount); + cpx_mtx_t ret; + cpx_mtx_init(&ret, 1, retLen); + cpx_t n; + for (unsigned int i = 0; i < retLen; i++) + { + unsigned char bitAVal = (i >> bitA) & 1; + unsigned char bitBVal = (i >> bitB) & 1; + unsigned char bitCVal = (i >> bitC) & 1; + unsigned char bitBNew = bitAVal ? bitCVal : bitBVal; + unsigned char bitCNew = bitAVal ? bitBVal : bitCVal; + unsigned int j = (i & ~((1 << bitB) | (1 << bitC))) | ((bitBNew << bitB) | (bitCNew << bitC)); + cpx_mtx_get(stateVector, 0, i, &n); + cpx_mtx_set(&ret, 0, j, &n); + } + cpx_mtx_free(stateVector); + stateVector->ptr = ret.ptr; + stateVector->rows = ret.rows; + stateVector->cols = ret.cols; +} + + +void qansel_toffoli(cpx_mtx_t* stateVector, unsigned char qubitCount, unsigned char bitA, unsigned char bitB, unsigned char bitC) +{ + if (bitA >= qubitCount || bitB >= qubitCount) return; + unsigned int retLen = (unsigned int)pow(2, qubitCount); + cpx_mtx_t ret; + cpx_mtx_init(&ret, 1, retLen); + cpx_t n; + for (unsigned int i = 0; i < retLen; i++) + { + unsigned char bitAVal = (i >> bitA) & 1; + unsigned char bitBVal = (i >> bitB) & 1; + unsigned char bitCVal = (i >> bitC) & 1; + unsigned char bitCNew = (bitAVal && bitBVal) ? !bitCVal : bitCVal; + unsigned int j = (i & ~(1 << bitC)) | (bitCNew << bitC); + cpx_mtx_get(stateVector, 0, i, &n); + cpx_mtx_set(&ret, 0, j, &n); + } + cpx_mtx_free(stateVector); + stateVector->ptr = ret.ptr; + stateVector->rows = ret.rows; + stateVector->cols = ret.cols; +} + +float* qansel_unitary(float theta, float phi, float lambda) +{ + cpx_mtx_t m; + cpx_t a, b, c, d; + a.real = cos(theta/2.0); + a.imaginary = 0; + b.real = -cos(lambda) * sin(theta/2.0); + b.imaginary = sin(lambda) * sin(theta/2.0); + c.real = cos(phi) * sin(theta/2.0); + c.imaginary = sin(phi) * sin(theta/2.0); + d.real = cos(phi + lambda) * cos(theta/2.0); + d.imaginary = sin(phi + lambda) * cos(theta/2.0); + cpx_mtx_init(&m, 2, 2); + cpx_mtx_set(&m, 0, 0, &a); + cpx_mtx_set(&m, 0, 1, &b); + cpx_mtx_set(&m, 1, 0, &c); + cpx_mtx_set(&m, 1, 1, &d); + return m.ptr; +} + +void qansel_instruction +( + cpx_mtx_t* stateVector, + int qubitCount, + unsigned char instr, + unsigned char index, + float arg0, + float arg1, + float arg2 +) +{ + cpx_mtx_t tmp; + cpx_mtx_t gate; + gate.rows = 2; + gate.cols = 2; + float* gate_ptr; + switch (instr) + { + case QANSEL_INSTRUCTION_H: gate_ptr = Hadamard; break; + case QANSEL_INSTRUCTION_X: gate_ptr = PauliX; break; + case QANSEL_INSTRUCTION_Y: gate_ptr = PauliY; break; + case QANSEL_INSTRUCTION_Z: gate_ptr = PauliZ; break; + case QANSEL_INSTRUCTION_S: gate_ptr = PhaseS; break; + case QANSEL_INSTRUCTION_T: gate_ptr = PhaseT; break; + case QANSEL_INSTRUCTION_RX: + case QANSEL_INSTRUCTION_RY: + case QANSEL_INSTRUCTION_RZ: + case QANSEL_INSTRUCTION_U1: + case QANSEL_INSTRUCTION_U2: + case QANSEL_INSTRUCTION_U3: + gate_ptr = qansel_unitary(arg0, arg1, arg2); + break; + default: gate_ptr = Identity; break; + } + + cpx_t n; + cpx_mtx_t filter; + cpx_mtx_init(&filter, 2, 2); + unsigned char qubit = qubitCount - (index) - 1; + if (qubit == 0) + { + memcpy(filter.ptr, gate_ptr, 8 * sizeof(float)); + } + else + { + memcpy(filter.ptr, Identity, 8 * sizeof(float)); + } + + for (unsigned char i = 1; i < qubitCount; i++) + { + if (index != 0x0F) + { + if (qubit == i) + { + gate.ptr = gate_ptr; + } + else + { + gate.ptr = Identity; + } + } + else + { + gate.ptr = gate_ptr; + } + + tmp.rows = filter.rows * gate.rows; + tmp.cols = filter.cols * gate.cols; + tmp.ptr = malloc(tmp.rows * (tmp.cols * 2) * sizeof(float)); + + #ifdef SPEED_TEST + printf("(%ix%i);(%ix%i) (knk)\n", tmp.rows, tmp.cols, gate.rows, gate.cols); + unsigned long int us1, us2; + us1 = get_time(); + cpx_mtx_knk_metal(tmp.ptr, filter.ptr, gate.ptr, filter.rows, filter.cols, gate.rows, gate.cols); + us2 = get_time(); + printf("\tMetal: %lu\n", us2 - us1); + us1 = get_time(); + cpx_mtx_knk_metal_2x2(tmp.ptr, filter.ptr, gate.ptr, filter.rows, filter.cols, gate.rows, gate.cols); + us2 = get_time(); + printf("\tMetal2x2: %lu\n", us2 - us1); + us1 = get_time(); + cpx_mtx_knk_threads(tmp.ptr, filter.ptr, gate.ptr, filter.rows, filter.cols, gate.rows, gate.cols); + us2 = get_time(); + printf("\tThreads: %lu\n", us2 - us1); + us1 = get_time(); + cpx_mtx_knk_threads_2x2(tmp.ptr, filter.ptr, gate.ptr, filter.rows, filter.cols, gate.rows, gate.cols); + us2 = get_time(); + printf("\tThreads2x2: %lu\n", us2 - us1); + us1 = get_time(); + cpx_mtx_knk(tmp.ptr, filter.ptr, gate.ptr, filter.rows, filter.cols, gate.rows, gate.cols); + us2 = get_time(); + printf("\tBare: %lu\n", us2 - us1); + us1 = get_time(); + cpx_mtx_knk_2x2(tmp.ptr, filter.ptr, gate.ptr, filter.rows, filter.cols, gate.rows, gate.cols); + us2 = get_time(); + printf("\tBare2x2: %lu\n", us2 - us1); + + //us1 = get_time(); + //cpx_mtx_knk(tmp.ptr, filter.ptr, gate.ptr, filter.rows, filter.cols, gate.rows, gate.cols); + //us2 = get_time(); + //printf("\tTranspose: %lu\n", us2 - us1); + #else + if (MODE == MODE_METAL && tmp.cols >= 64) + { + cpx_mtx_knk_metal_2x2(tmp.ptr, filter.ptr, gate.ptr, filter.rows, filter.cols, gate.rows, gate.cols); + } + else if ((MODE == MODE_THREADED || MODE == MODE_METAL_THREADED) && tmp.cols >= 64) + { + cpx_mtx_knk_threads_2x2(tmp.ptr, filter.ptr, gate.ptr, filter.rows, filter.cols, gate.rows, gate.cols); + } + else + { + cpx_mtx_knk_2x2(tmp.ptr, filter.ptr, gate.ptr, filter.rows, filter.cols, gate.rows, gate.cols); + } + #endif + + free(filter.ptr); + filter.ptr = tmp.ptr; + filter.rows = tmp.rows; + filter.cols = tmp.cols; + } + + cpx_mtx_init(&tmp, stateVector->rows, stateVector->cols); + + #ifdef SPEED_TEST + printf("%ix%i (dot)\n", tmp.rows, tmp.cols); + unsigned long int us1, us2; + us1 = get_time(); + cpx_mtx_dot_metal(tmp.ptr, stateVector->ptr, filter.ptr, stateVector->rows, stateVector->cols, filter.rows, filter.cols); + us2 = get_time(); + printf("\tMetal: %lu\n", us2 - us1); + us1 = get_time(); + cpx_mtx_dot_threads(tmp.ptr, stateVector->ptr, filter.ptr, stateVector->rows, stateVector->cols, filter.rows, filter.cols); + us2 = get_time(); + printf("\tThreads: %lu\n", us2 - us1); + us1 = get_time(); + cpx_mtx_dot(tmp.ptr, stateVector->ptr, filter.ptr, stateVector->rows, stateVector->cols, filter.rows, filter.cols); + us2 = get_time(); + printf("\tBare: %lu\n", us2 - us1); + #else + if ((MODE == MODE_METAL || MODE == MODE_METAL_THREADED) && tmp.cols >= 64) + { + cpx_mtx_dot_metal(tmp.ptr, stateVector->ptr, filter.ptr, stateVector->rows, stateVector->cols, filter.rows, filter.cols); + } + else if (MODE == MODE_THREADED && tmp.cols >= 64) + { + cpx_mtx_dot_threads(tmp.ptr, stateVector->ptr, filter.ptr, stateVector->rows, stateVector->cols, filter.rows, filter.cols); + } + else + { + cpx_mtx_dot(tmp.ptr, stateVector->ptr, filter.ptr, stateVector->rows, stateVector->cols, filter.rows, filter.cols); + } + #endif + free(stateVector->ptr); + stateVector->ptr = tmp.ptr; + free(filter.ptr); + if (instr == QANSEL_INSTRUCTION_U1 || instr == QANSEL_INSTRUCTION_U2 || instr == QANSEL_INSTRUCTION_U3) + { + free(gate_ptr); + } +} + +unsigned char qansel_measure(cpx_mtx_t* stateVector, unsigned char qubitCount, unsigned char qubit) +{ + unsigned int qubitCountPow2 = (unsigned int)pow(2, qubitCount); + cpx_t n; + float prob0 = 0; + for (unsigned int i = 0; i < qubitCountPow2; i++) + { + unsigned char bit = (i >> qubit) & 1; + cpx_mtx_get(stateVector, 0, i, &n); + if (bit == 0) prob0 += cpx_magsqr(&n); + } + + float r = qansel_rand(); + unsigned char newBit = r < prob0 ? 0 : 1; + float probTot = 0; + for (unsigned int i = 0; i < qubitCountPow2; i++) + { + unsigned char bit = (i >> qubit) & 1; + cpx_mtx_get(stateVector, 0, i, &n); + if (bit != newBit) + { + n.real = 0; + n.imaginary = 0; + } + else + { + probTot += cpx_magsqr(&n); + } + cpx_mtx_set(stateVector, 0, i, &n); + } + + float multiplier = sqrt(1 / probTot); + for (unsigned int i = 0; i < qubitCountPow2; i++) + { + unsigned char bit = (i >> qubit) & 1; + cpx_mtx_get(stateVector, 0, i, &n); + if (bit == newBit) + { + n.real *= multiplier; + n.imaginary *= multiplier; + } + cpx_mtx_set(stateVector, 0, i, &n); + } + + return newBit; +} + +int qansel_get_instruction_bitmax(unsigned char* ptr, int offset, int* bitmax, int* qbitmax) +{ + unsigned char a0, a1, a2; + *bitmax = 0; + *qbitmax = 0; + switch (ptr[offset]) + { + case QANSEL_INSTRUCTION_X: + case QANSEL_INSTRUCTION_Y: + case QANSEL_INSTRUCTION_Z: + case QANSEL_INSTRUCTION_H: + case QANSEL_INSTRUCTION_S: + case QANSEL_INSTRUCTION_T: + case QANSEL_INSTRUCTION_RX: + case QANSEL_INSTRUCTION_RY: + case QANSEL_INSTRUCTION_RZ: + case QANSEL_INSTRUCTION_U1: + case QANSEL_INSTRUCTION_U2: + case QANSEL_INSTRUCTION_U3: + case QANSEL_INSTRUCTION_BARRIER: + case QANSEL_INSTRUCTION_DENSITY: + case QANSEL_INSTRUCTION_BORN: + a0 = ptr[offset + 1]; + if (a0 > 0x0D && a0 != 0x0F) return 0; + if (a0 != 0x0F) *qbitmax = a0 + 1; + return 1; + case QANSEL_INSTRUCTION_SAMPLE: + case QANSEL_INSTRUCTION_IF_E: + case QANSEL_INSTRUCTION_IF_NE: + case QANSEL_INSTRUCTION_IF_G: + case QANSEL_INSTRUCTION_IF_GE: + case QANSEL_INSTRUCTION_IF_L: + case QANSEL_INSTRUCTION_IF_LE: + a0 = ptr[offset + 1]; + if ((a0 > 0x1D || a0 < 0x10) && a0 != 0x1F) return 0; + if (a0 != 0x1F) *bitmax = (a0 - 0x10) + 1; + return 1; + case QANSEL_INSTRUCTION_RESET: + case QANSEL_INSTRUCTION_PRINT: + a0 = ptr[offset + 1]; + if (a0 == 0xFF) return 1; + if (a0 < 0x10) + { + if (a0 > 0x0D && a0 != 0x0F) return 0; + if (a0 != 0x0F) *qbitmax = a0 + 1; + return 1; + } + else + { + if ((a0 > 0x1D || a0 < 0x10) && a0 != 0x1F) return 0; + if (a0 != 0x1F) *bitmax = (a0 - 0x10) + 1; + return 1; + } + return 0; + case QANSEL_INSTRUCTION_CX: + case QANSEL_INSTRUCTION_SWAP: + a0 = ptr[offset + 1]; + a1 = ptr[offset + 2]; + if (a0 > 0x0D) return 0; + if (a1 > 0x0D) return 0; + *qbitmax = (a0 > a1 ? a0 : a1) + 1; + return 1; + case QANSEL_INSTRUCTION_CCX: + case QANSEL_INSTRUCTION_CSWAP: + a0 = ptr[offset + 1]; + a1 = ptr[offset + 2]; + a2 = ptr[offset + 3]; + if (a0 > 0x0D || a1 > 0x0D || a2 > 0x0D) return 0; + *qbitmax = ((a0 > a1) && (a0 > a2) ? a0 : ((a1 > a0) && (a1 > a2) ? a1 : a2)) + 1; + return 1; + case QANSEL_INSTRUCTION_MEASURE: + a0 = ptr[offset + 1]; + a1 = ptr[offset + 2]; + if (a0 > 0x0D) return 0; + if (a1 > 0x1D || a1 < 0x10) return 0; + *qbitmax = a0 + 1; + *bitmax = (a1 - 0x10) + 1; + return 1; + } + return 0; +} + +int qansel_get_instruction_size(unsigned char instr) +{ + switch (instr) + { + case QANSEL_INSTRUCTION_X: return 1 + 1; + case QANSEL_INSTRUCTION_Y: return 1 + 1; + case QANSEL_INSTRUCTION_Z: return 1 + 1; + case QANSEL_INSTRUCTION_H: return 1 + 1; + case QANSEL_INSTRUCTION_S: return 1 + 1; + case QANSEL_INSTRUCTION_T: return 1 + 1; + case QANSEL_INSTRUCTION_RX: return 1 + 1 + sizeof(float); + case QANSEL_INSTRUCTION_RY: return 1 + 1 + sizeof(float); + case QANSEL_INSTRUCTION_RZ: return 1 + 1 + sizeof(float); + case QANSEL_INSTRUCTION_U1: return 1 + 1 + sizeof(float); + case QANSEL_INSTRUCTION_U2: return 1 + 1 + sizeof(float) * 2; + case QANSEL_INSTRUCTION_U3: return 1 + 1 + sizeof(float) * 3; + case QANSEL_INSTRUCTION_CX: return 1 + 2; + case QANSEL_INSTRUCTION_SWAP: return 1 + 2; + case QANSEL_INSTRUCTION_CCX: return 1 + 3; + case QANSEL_INSTRUCTION_CSWAP: return 1 + 3; + case QANSEL_INSTRUCTION_MEASURE: return 1 + 2; + case QANSEL_INSTRUCTION_SAMPLE: return 1 + 1; + case QANSEL_INSTRUCTION_DENSITY: return 1 + 1; + case QANSEL_INSTRUCTION_BORN: return 1 + 1; + case QANSEL_INSTRUCTION_IF_E: return 1 + 1 + sizeof(unsigned short); + case QANSEL_INSTRUCTION_IF_NE: return 1 + 1 + sizeof(unsigned short); + case QANSEL_INSTRUCTION_IF_G: return 1 + 1 + sizeof(unsigned short); + case QANSEL_INSTRUCTION_IF_GE: return 1 + 1 + sizeof(unsigned short); + case QANSEL_INSTRUCTION_IF_L: return 1 + 1 + sizeof(unsigned short); + case QANSEL_INSTRUCTION_IF_LE: return 1 + 1 + sizeof(unsigned short); + case QANSEL_INSTRUCTION_RAND: return 1; + case QANSEL_INSTRUCTION_HVAR: return 1 + sizeof(float); + case QANSEL_INSTRUCTION_RESET: return 1 + 1; + case QANSEL_INSTRUCTION_PRINT: return 1 + 1; + case QANSEL_INSTRUCTION_BARRIER: return 1 + 1; + case QANSEL_INSTRUCTION_EXIT: return 1; + } + return 0; +} + +void qansel_born(cpx_mtx_t* stateVector, int PC, int qubitCount, unsigned char q0) +{ + unsigned int qubitCountPow2 = (unsigned int)pow(2, qubitCount); + if (q0 == 0x0F) + { + for (unsigned int j = 0; j < qubitCountPow2; j++) + { + unsigned int tmp = j; + for (unsigned char k = 0; k < qubitCount; k++) + { + putchar('0' + (tmp >> (qubitCount - 1) & 1)); + tmp <<= 1; + } + cpx_t n; + cpx_mtx_get(stateVector, 0, j, &n); + printf(": %.1f%%\n", cpx_magsqr(&n) * 100); + } + } + else if (q0 <= 0x0D) + { + float prob = 0; + for (unsigned int j = 0; j < qubitCountPow2; j++) + { + cpx_t n; + cpx_mtx_get(stateVector, 0, j, &n); + if ((j >> q0) & 1) + { + prob += cpx_magsqr(&n); + } + } + printf("0: %.1f%%\n", (1 - prob) * 100.0); + printf("1: %.1f%%\n", prob * 100.0); + } +} + +void qansel_density_or_print(cpx_mtx_t* stateVector, unsigned char* bitVector, unsigned char density, int bitCount, int qubitCount, unsigned char a0) +{ + unsigned int qubitCountPow2 = (unsigned int)pow(2, qubitCount); + if (a0 == 0x0F || a0 == 0x1F || a0 == 0xFF) + { + if (a0 == 0x0F || a0 == 0xFF) + { + printf("[ "); cpx_mtx_print(stateVector); printf(" ]\n"); + } + if (a0 == 0x1F || a0 == 0xFF) + { + for (int32_t j = bitCount - 1; j >= 0; j--) + { + putchar('0' + bitVector[j]); + } + putchar('\n'); + } + } + else if (a0 >= 0x10 && a0 <= 0x1D) + { + putchar('0' + bitVector[a0 - 0x10]); + putchar('\n'); + } + else + { + cpx_mtx_t tmp; + cpx_mtx_init(&tmp, 1, 2); + for (unsigned int j = 0; j < qubitCountPow2; j++) + { + if ((j >> a0) & 1) + { + cpx_t a, b; + cpx_mtx_get(&tmp, 0, 1, &a); + cpx_mtx_get(stateVector, 0, j, &b); + a.real += b.real; + a.imaginary += b.imaginary; + cpx_mtx_set(&tmp, 0, 1, &a); + } + else + { + cpx_t a, b; + cpx_mtx_get(&tmp, 0, 0, &a); + cpx_mtx_get(stateVector, 0, j, &b); + a.real += b.real; + a.imaginary += b.imaginary; + cpx_mtx_set(&tmp, 0, 0, &a); + } + } + float multiplier = 0; + cpx_t n; + cpx_mtx_get(&tmp, 0, 0, &n); + multiplier += cpx_magsqr(&n); + cpx_mtx_get(&tmp, 0, 1, &n); + multiplier += cpx_magsqr(&n); + multiplier = sqrt(1 / multiplier); + n.real *= multiplier; + n.imaginary *= multiplier; + cpx_mtx_set(&tmp, 0, 1, &n); + cpx_mtx_get(&tmp, 0, 0, &n); + n.real *= multiplier; + n.imaginary *= multiplier; + cpx_mtx_set(&tmp, 0, 0, &n); + + if (density) + { + cpx_t a, b, c, d, x, y, z, w; + cpx_mtx_get(&tmp, 0, 0, &a); + cpx_mtx_get(&tmp, 0, 1, &b); + cpx_mtx_get(&tmp, 0, 0, &c); + cpx_mtx_get(&tmp, 0, 1, &d); + c.imaginary *= -1; + d.imaginary *= -1; + cpx_mul(&x, &a, &c); + cpx_mul(&y, &a, &d); + cpx_mul(&z, &b, &c); + cpx_mul(&w, &b, &d); + char* sx = cpx_str(&x); + char* sy = cpx_str(&y); + char* sz = cpx_str(&z); + char* sw = cpx_str(&w); + printf("[ %s, %s ]\n", sx, sy); + printf("[ %s, %s ]\n", sz, sw); + free(sx); + free(sy); + free(sz); + free(sw); + } + else + { + printf("[ "); cpx_mtx_print(&tmp); printf(" ]\n"); + } + cpx_mtx_free(&tmp); + } +} + +float qansel_get_float(unsigned char* program, int offset) +{ + float ret; + memcpy(&ret, program + offset, sizeof(float)); + return ret; +} + +short qansel_get_short(unsigned char* program, int offset) +{ + short ret; + memcpy(&ret, program + offset, sizeof(short)); + return ret; +} + +int qansel_get_int(unsigned char* program, int offset) +{ + int ret; + memcpy(&ret, program + offset, sizeof(int)); + return ret; +} + +void qansel_reset(cpx_mtx_t* stateVector, unsigned char* bitVector, int qubitCount, int bitCount, unsigned char q0) +{ + unsigned int qubitCountPow2 = (unsigned int)pow(2, qubitCount); + if (q0 == 0xFF) + { + cpx_mtx_set2(stateVector, 0, 0, 1, 0); + for (unsigned int j = 1; j < qubitCountPow2; j++) + { + cpx_mtx_set2(stateVector, 0, j, 0, 0); + } + for (unsigned char j = 0; j < bitCount; j++) + { + bitVector[j] = 0; + } + } + else if (q0 == 0x0F) + { + cpx_mtx_set2(stateVector, 0, 0, 1, 0); + for (unsigned int j = 1; j < qubitCountPow2; j++) + { + cpx_mtx_set2(stateVector, 0, j, 0, 0); + } + } + else if (q0 == 0x1F) + { + for (unsigned char j = 0; j < bitCount; j++) + { + bitVector[j] = 0; + } + } + else if (q0 <= 0x0D) + { + unsigned char bit = qansel_measure(stateVector, qubitCount, q0); + if (bit) + { + qansel_instruction(stateVector, qubitCount, QANSEL_INSTRUCTION_X, q0, 0, 0, 0); + } + } + else if (q0 >= 0x10 && q0 <= 0x1D) + { + bitVector[q0 - 0x10] = 0; + } +} + +unsigned char qansel_compare(unsigned char* bitVector, int bitCount, int PC, unsigned char a0, short op) +{ + unsigned char ret = 0; + short val; + if (a0 == 0x1F) + { + val = 0; + for (int32_t j = bitCount - 1; j >= 0; j--) + { + val = (val << 1) | bitVector[j]; + } + if (val == op) ret |= QANSEL_FLAGS_EQUAL; + if (val > op) ret |= QANSEL_FLAGS_GREATER; + if (val < op) ret |= QANSEL_FLAGS_LESSER; + } + else if (a0 >= 0x10 && a0 <= 0x1D) + { + val = bitVector[a0 - 0x10]; + if (val == op) ret |= QANSEL_FLAGS_EQUAL; + if (val > op) ret |= QANSEL_FLAGS_GREATER; + if (val < op) ret |= QANSEL_FLAGS_LESSER; + } + return ret; +} + +void qansel_crawl(unsigned char* program, int programSize, int* qubitCount, int* bitCount, int* sample) +{ + printf("Crawling program . . .\n"); + int PC = 0; + *qubitCount = 0; + *bitCount = 0; + *sample = 0xFF; + while (PC < programSize) + { + int next = qansel_get_instruction_size(program[PC]); + printf("|%s|\n", qansel_instruction_to_string(program[PC])); + if (program[PC] == QANSEL_INSTRUCTION_SAMPLE) + { + if ((program[PC + 1] < 0x10 || program[PC + 1] > 0x1D) && program[PC + 1] != 0x1F) + { + fprintf(stderr, "QAnsel (%04X): Invalid index.\n", PC); + } + else + { + *sample = program[PC + 1] - 0x10; + } + } + if (next == 0) + { + printf("QAnsel (%04X): Invalid instruction 0x%02x.\n", PC, program[PC]); + exit(1); + } + int bitmax, qbitmax; + int success = qansel_get_instruction_bitmax(program, PC, &bitmax, &qbitmax); + if (!success) + { + fprintf(stderr, "QAnsel (%04X): Invalid index (%s).\n", PC); + exit(1); + } + if (bitmax > *bitCount) *bitCount = bitmax; + if (qbitmax > *qubitCount) *qubitCount = qbitmax; + PC += next; + } + printf("Quantum bits allocated: %i\n", *qubitCount); + printf("Classical bits allocated: %i\n", *bitCount); +} + +void qansel_run(unsigned char* program, int programSize, int qubitCount, int bitCount, unsigned char* outputBitVector) +{ + int PC = 0; + unsigned int qubitCountPow2 = (unsigned int)pow(2, qubitCount); + unsigned char bitVector[bitCount]; + memset(bitVector, 0, bitCount); + cpx_mtx_t stateVector; + cpx_mtx_init(&stateVector, 1, qubitCountPow2); + cpx_mtx_set2(&stateVector, 0, 0, 1, 0); + //if (gfx) display(&stateVector, qubitCount); + unsigned char skip = 0, a0 = 0, a1 = 0, a2 = 0; + unsigned char flags = 0; + unsigned short tmp = 0; + + while (PC < programSize) + { + //printf("%i;%i\n", PC, programSize); + int next = qansel_get_instruction_size(program[PC]); + if (skip) + { + skip = 0; + } + else + { + unsigned char instr = program[PC]; + //printf("-----------------------------------\n"); + //qansel_density_or_print(&stateVector, bitVector, 0, bitCount, qubitCount, 0x0F); + //qansel_density_or_print(&stateVector, bitVector, 0, bitCount, qubitCount, 0x1F); + //printf("%s(%i, %i, %i)(%f, %f, %f)\n", qansel_instruction_to_string(instr), program[PC+1], program[PC+2], program[PC], qansel_get_float(program, PC + 2), qansel_get_float(program, PC + 2 + sizeof(float)), qansel_get_float(program, PC + 2) + sizeof(float) * 2); + switch (instr) + { + case QANSEL_INSTRUCTION_X: + case QANSEL_INSTRUCTION_Y: + case QANSEL_INSTRUCTION_Z: + case QANSEL_INSTRUCTION_H: + case QANSEL_INSTRUCTION_S: + case QANSEL_INSTRUCTION_T: + a0 = program[PC + 1]; + qansel_instruction(&stateVector, qubitCount, instr, program[PC + 1], 0, 0, 0); + break; + case QANSEL_INSTRUCTION_RX: + a0 = program[PC + 1]; + qansel_instruction + ( + &stateVector, qubitCount, instr, a0, + M_PI / 2, -M_PI / 2, qansel_get_float(program, PC + 2) - (M_PI / 2) + ); + break; + case QANSEL_INSTRUCTION_RY: + case QANSEL_INSTRUCTION_U1: + a0 = program[PC + 1]; + qansel_instruction + ( + &stateVector, qubitCount, instr, a0, + qansel_get_float(program, PC + 2), 0, 0 + ); + break; + case QANSEL_INSTRUCTION_RZ: + a0 = program[PC + 1]; + qansel_instruction + ( + &stateVector, qubitCount, instr, a0, + 0, 0, qansel_get_float(program, PC + 2) + ); + break; + case QANSEL_INSTRUCTION_U2: + a0 = program[PC + 1]; + qansel_instruction + ( + &stateVector, qubitCount, instr, a0, + qansel_get_float(program, PC + 2), + qansel_get_float(program, PC + 2 + sizeof(float)), + 0 + ); + break; + case QANSEL_INSTRUCTION_U3: + a0 = program[PC + 1]; + qansel_instruction + ( + &stateVector, qubitCount, instr, a0, + qansel_get_float(program, PC + 2), + qansel_get_float(program, PC + 2 + sizeof(float)), + qansel_get_float(program, PC + 2 + sizeof(float) * 2) + ); + break; + case QANSEL_INSTRUCTION_CX: + a0 = program[PC + 1]; + a1 = program[PC + 2]; + qansel_cnot(&stateVector, qubitCount, a0, a1); + break; + case QANSEL_INSTRUCTION_SWAP: + a0 = program[PC + 1]; + a1 = program[PC + 2]; + qansel_swap(&stateVector, qubitCount, a0, a1); + break; + case QANSEL_INSTRUCTION_CCX: + a0 = program[PC + 1]; + a1 = program[PC + 2]; + a2 = program[PC + 3]; + qansel_toffoli(&stateVector, qubitCount, a0, a1, a2); + break; + case QANSEL_INSTRUCTION_CSWAP: + a0 = program[PC + 1]; + a1 = program[PC + 2]; + a2 = program[PC + 3]; + qansel_fredkin(&stateVector, qubitCount, a0, a1, a2); + break; + case QANSEL_INSTRUCTION_MEASURE: + a0 = program[PC + 1]; + a1 = program[PC + 2] - 0x10; + bitVector[a1] = qansel_measure(&stateVector, qubitCount, a0); + break; + case QANSEL_INSTRUCTION_BORN: + a0 = program[PC + 1]; + qansel_born(&stateVector, PC, qubitCount, a0); + break; + case QANSEL_INSTRUCTION_DENSITY: + a0 = program[PC + 1]; + qansel_density_or_print(&stateVector, bitVector, 1, bitCount, qubitCount, a0); + break; + case QANSEL_INSTRUCTION_PRINT: + a0 = program[PC + 1]; + qansel_density_or_print(&stateVector, bitVector, 0, bitCount, qubitCount, a0); + break; + case QANSEL_INSTRUCTION_BARRIER: + a0 = program[PC + 1]; + break; + case QANSEL_INSTRUCTION_RESET: + a0 = program[PC + 1]; + qansel_reset(&stateVector, bitVector, qubitCount, bitCount, a0); + break; + case QANSEL_INSTRUCTION_HVAR: + HIDDEN_VARIABLE = 1; + float tmp1 = qansel_get_float(program, PC + 1); + unsigned int tmp2; + memcpy(&tmp2, &tmp1, sizeof(unsigned int)); + srand(tmp2); + break; + case QANSEL_INSTRUCTION_RAND: + HIDDEN_VARIABLE = 0; + break; + case QANSEL_INSTRUCTION_IF_E: + a0 = program[PC + 1]; + tmp = qansel_get_short(program, PC + 2); + flags = qansel_compare(bitVector, bitCount, PC, a0, tmp); + skip = 1; if (flags & QANSEL_FLAGS_EQUAL) skip = 0; + break; + case QANSEL_INSTRUCTION_IF_NE: + a0 = program[PC + 1]; + tmp = qansel_get_short(program, PC + 2); + flags = qansel_compare(bitVector, bitCount, PC, a0, tmp); + skip = 1; if (!(flags & QANSEL_FLAGS_EQUAL)) skip = 0; + break; + case QANSEL_INSTRUCTION_IF_G: + a0 = program[PC + 1]; + tmp = qansel_get_short(program, PC + 2); + flags = qansel_compare(bitVector, bitCount, PC, a0, tmp); + skip = 1; if (flags & QANSEL_FLAGS_GREATER) skip = 0; + break; + case QANSEL_INSTRUCTION_IF_GE: + a0 = program[PC + 1]; + tmp = qansel_get_short(program, PC + 2); + flags = qansel_compare(bitVector, bitCount, PC, a0, tmp); + skip = 1; if ((flags & QANSEL_FLAGS_GREATER) && (flags & QANSEL_FLAGS_EQUAL)) skip = 0; + break; + case QANSEL_INSTRUCTION_IF_L: + a0 = program[PC + 1]; + tmp = qansel_get_short(program, PC + 2); + flags = qansel_compare(bitVector, bitCount, PC, a0, tmp); + skip = 1; if (flags & QANSEL_FLAGS_LESSER) skip = 0; + break; + case QANSEL_INSTRUCTION_IF_LE: + a0 = program[PC + 1]; + tmp = qansel_get_short(program, PC + 2); + flags = qansel_compare(bitVector, bitCount, PC, a0, tmp); + skip = 1; if ((flags & QANSEL_FLAGS_LESSER) && (flags & QANSEL_FLAGS_EQUAL)) skip = 0; + break; + case QANSEL_INSTRUCTION_SAMPLE: break; + + } + } + PC += next; + } + if (outputBitVector != NULL) + { + for (int i = 0; i < bitCount; i++) + { + outputBitVector[i] = bitVector[i]; + } + } +} + +void qansel_execute(unsigned char* buff, int sizeofbuff) +{ + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + float seed = (float)((unsigned long)ts.tv_sec * 1000000000LL + ts.tv_nsec); + qansel_rand_s(seed); + + unsigned short vals; + float valf; + int pos = 0; + + int qubitCount, bitCount, sample; + qansel_crawl(buff, sizeofbuff, &qubitCount, &bitCount, &sample); + if (sample != 0xFF) + { + unsigned short stats[65536]; + for (unsigned int i = 0; i < (1 << bitCount); i++) + { + stats[i] = 0; + } + unsigned char bitVect[bitCount]; + memset(bitVect, 0, bitCount); + for (int i = 0; i < bitCount; i++) bitVect[i] = 0; + unsigned int shots = 1000; + for (unsigned int i = 0; i < shots; i++) + { + qansel_run(buff, sizeofbuff, qubitCount, bitCount, bitVect); + unsigned short stat = 0; + for (signed char j = bitCount - 1; j >= 0; j--) + { + stat = (stat << 1) | bitVect[j]; + } + stats[stat]++; + } + unsigned int count = 0; + for (unsigned int i = 0; i < (1 << bitCount); i++) + { + unsigned int tmp = i; + for (unsigned char j = 0; j < bitCount; j++) + { + unsigned char bit = (tmp >> (bitCount - 1) & 1); + if (j == (bitCount - sample - 1) && bit) + { + count += stats[i]; + } + if (sample == 0x0F) + { + putchar('0' + bit); + } + tmp <<= 1; + } + if (sample == 0x0F) + { + printf(": %.1f%%\n", ((float)stats[i] / (float)shots) * (float)100); + } + } + if (sample != 0x0F) + { + float prob = ((float)count / (float)shots) * (float)100; + printf("0: %.1f%%\n", ((float)100)-prob); + printf("1: %.1f%%\n", prob); + } + } + else + { + qansel_run(buff, sizeofbuff, qubitCount, bitCount, NULL); + } +} diff --git a/src/oldex.mm b/src/oldex.mm new file mode 100644 index 0000000..bbb35ee --- /dev/null +++ b/src/oldex.mm @@ -0,0 +1,127 @@ + + //0+0 + QANSEL_INSTRUCTION_CCX, 0x00, 0x01, 0x02, + QANSEL_INSTRUCTION_CX, 0x00, 0x01, + QANSEL_INSTRUCTION_MEASURE, 0x01, 0x10, + QANSEL_INSTRUCTION_MEASURE, 0x02, 0x11, + QANSEL_INSTRUCTION_PRINT, 0x1F, + QANSEL_INSTRUCTION_RESET, 0xFF, + + //0+1 + QANSEL_INSTRUCTION_X, 0x00, + QANSEL_INSTRUCTION_CCX, 0x00, 0x01, 0x02, + QANSEL_INSTRUCTION_CX, 0x00, 0x01, + QANSEL_INSTRUCTION_MEASURE, 0x01, 0x10, + QANSEL_INSTRUCTION_MEASURE, 0x02, 0x11, + QANSEL_INSTRUCTION_PRINT, 0x1F, + QANSEL_INSTRUCTION_RESET, 0xFF, + + //1+0 + QANSEL_INSTRUCTION_X, 0x01, + QANSEL_INSTRUCTION_CCX, 0x00, 0x01, 0x02, + QANSEL_INSTRUCTION_CX, 0x00, 0x01, + QANSEL_INSTRUCTION_MEASURE, 0x01, 0x10, + QANSEL_INSTRUCTION_MEASURE, 0x02, 0x11, + QANSEL_INSTRUCTION_PRINT, 0x1F, + QANSEL_INSTRUCTION_RESET, 0xFF, + + //1+1 + QANSEL_INSTRUCTION_X, 0x00, + QANSEL_INSTRUCTION_X, 0x01, + QANSEL_INSTRUCTION_CCX, 0x00, 0x01, 0x02, + QANSEL_INSTRUCTION_CX, 0x00, 0x01, + QANSEL_INSTRUCTION_MEASURE, 0x01, 0x10, + QANSEL_INSTRUCTION_MEASURE, 0x02, 0x11, + QANSEL_INSTRUCTION_PRINT, 0x1F, + QANSEL_INSTRUCTION_RESET, 0xFF, + + + + + QANSEL_INSTRUCTION_U3, 0x00, 0xED, 00, 00, 00, 0xED, 00, 00, 00, 0xED, 00, 00, 00, + QANSEL_INSTRUCTION_PRINT, 0x00, + + QANSEL_INSTRUCTION_H, 0x01, + QANSEL_INSTRUCTION_CX, 0x01, 0x02, + + QANSEL_INSTRUCTION_CX, 0x00, 0x01, + QANSEL_INSTRUCTION_H, 0x00, + + QANSEL_INSTRUCTION_MEASURE, 0x00, 0x10, + QANSEL_INSTRUCTION_MEASURE, 0x01, 0x11, + + QANSEL_INSTRUCTION_IF_E, 0x1F, 0xED, 0x00, + QANSEL_INSTRUCTION_Z, 0x02, + QANSEL_INSTRUCTION_IF_E, 0x1F, 0xED, 0x00, + QANSEL_INSTRUCTION_X, 0x02, + QANSEL_INSTRUCTION_IF_E, 0x1F, 0xED, 0x00, + QANSEL_INSTRUCTION_X, 0x02, + QANSEL_INSTRUCTION_IF_E, 0x1F, 0xED, 0x00, + QANSEL_INSTRUCTION_Z, 0x02, + + QANSEL_INSTRUCTION_RESET, 0x00, + QANSEL_INSTRUCTION_RESET, 0x01, + QANSEL_INSTRUCTION_PRINT, 0x02, + + + + //Host generates random bits + // for the two players. + QANSEL_INSTRUCTION_H, 0x00, + QANSEL_INSTRUCTION_H, 0x01, + QANSEL_INSTRUCTION_MEASURE, 0x00, 0x10, + QANSEL_INSTRUCTION_MEASURE, 0x01, 0x11, + QANSEL_INSTRUCTION_RESET, 0x00, + QANSEL_INSTRUCTION_RESET, 0x01, + + //Two players are also provided + // an entangled qubit. + QANSEL_INSTRUCTION_H, 0x00, + QANSEL_INSTRUCTION_CX, 0x00, 0x01, + + //Player X strategy + //if(c[0]==0) do nothing + QANSEL_INSTRUCTION_IF_E, 0x10, 0xEE, 0x00, + QANSEL_INSTRUCTION_RY, 0x00, 0xEE, 0x00, 0x00, 0x00, + + //Player Y strategy + QANSEL_INSTRUCTION_IF_E, 0x11, 0xEE, 0x00, + QANSEL_INSTRUCTION_RY, 0x01, 0xEE, 0x00, 0x00, 0x00, + QANSEL_INSTRUCTION_IF_E, 0x11, 0xEE, 0x00, + QANSEL_INSTRUCTION_RY, 0x01, 0xEE, 0x00, 0x00, 0x00, + + //Transfer to host + QANSEL_INSTRUCTION_MEASURE, 0x00, 0x12, + QANSEL_INSTRUCTION_MEASURE, 0x01, 0x13, + + //a xor b + QANSEL_INSTRUCTION_CX, 0x00, 0x01, + QANSEL_INSTRUCTION_MEASURE, 0x01, 0x13, + + //Load x and y + QANSEL_INSTRUCTION_RESET, 0x00, + QANSEL_INSTRUCTION_IF_E, 0x10, 0xEE, 0x00, + QANSEL_INSTRUCTION_X, 0x00, + QANSEL_INSTRUCTION_RESET, 0x01, + QANSEL_INSTRUCTION_IF_E, 0x11, 0xEE, 0x00, + QANSEL_INSTRUCTION_X, 0x01, + + //x and y + QANSEL_INSTRUCTION_CCX, 0x00, 0x01, 0x02, + QANSEL_INSTRUCTION_MEASURE, 0x02, 0x12, + + //Load (a xor b) and (x and y) + QANSEL_INSTRUCTION_RESET, 0x00, + QANSEL_INSTRUCTION_IF_E, 0x12, 0xEE, 0x00, + QANSEL_INSTRUCTION_X, 0x00, + QANSEL_INSTRUCTION_RESET, 0x01, + QANSEL_INSTRUCTION_IF_E, 0x13, 0xEE, 0x00, + QANSEL_INSTRUCTION_X, 0x01, + + //(a xor b) = (x and y) + QANSEL_INSTRUCTION_CX, 0x00, 0x01, + QANSEL_INSTRUCTION_X, 0x01, + + //Store final results + QANSEL_INSTRUCTION_MEASURE, 0x01, 0x10, + QANSEL_INSTRUCTION_SAMPLE, 0x10 \ No newline at end of file