From: miha-q <> Date: Fri, 2 Aug 2024 21:23:16 +0000 (-0400) Subject: Fri Aug 2 05:23:16 PM EDT 2024 X-Git-Url: http://www.foleosoft.com/?a=commitdiff_plain;h=bb3c1193b8b5d45b597710913cbcc3a9b00ed0f0;p=QAnsel.git Fri Aug 2 05:23:16 PM EDT 2024 --- diff --git a/examples/ghz.txt b/examples/ghz.txt index 07e4689..8bd66a2 100644 --- a/examples/ghz.txt +++ b/examples/ghz.txt @@ -1,8 +1,3 @@ qreg q[2]; -creg c[2]; -x q[0]; -z q[1]; -swap q[0], q[1]; -measure q[0] -> c[0]; -measure q[1] -> c[1]; -sample c; \ No newline at end of file +h q[0]; +sample q; diff --git a/src/bytecode.c b/src/bytecode.c index 7327f7e..7033c3a 100644 --- a/src/bytecode.c +++ b/src/bytecode.c @@ -25,6 +25,7 @@ const char* qansel_instruction_to_string(unsigned char instr) case QANSEL_INSTRUCTION_MEASURE: return "measure"; case QANSEL_INSTRUCTION_DENSITY: return "density"; case QANSEL_INSTRUCTION_BORN: return "born"; + case QANSEL_INSTRUCTION_BSAMPLE: return "bsample"; case QANSEL_INSTRUCTION_IF_E: return "if=="; case QANSEL_INSTRUCTION_IF_NE: return "if!="; case QANSEL_INSTRUCTION_IF_G: return "if>"; @@ -509,6 +510,7 @@ int qansel_get_instruction_bitmax(unsigned char* ptr, int offset, int* bitmax, i return 1; case QANSEL_INSTRUCTION_BARRIER: case QANSEL_INSTRUCTION_BORN: + case QANSEL_INSTRUCTION_BSAMPLE: a0 = ptr[offset + 1]; if (a0 > QANSEL_QBOUND_UPPER && a0 != QANSEL_ALL_QUANTUM) return 0; if (a0 != QANSEL_ALL_QUANTUM) *qbitmax = a0 + 1; @@ -593,6 +595,7 @@ int qansel_get_instruction_size(unsigned char instr) case QANSEL_INSTRUCTION_CSWAP: return 1 + 3; case QANSEL_INSTRUCTION_MEASURE: return 1 + 2; case QANSEL_INSTRUCTION_DENSITY: return 1 + 1; + case QANSEL_INSTRUCTION_BSAMPLE: 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); @@ -645,6 +648,7 @@ void qansel_get_barrier(QBytecode** qbc, int idx) (*qbc)[idx].barrier[0] = (*qbc)[idx].bytes[1]; (*qbc)[idx].barrier[1] = (*qbc)[idx].bytes[2]; return; + case QANSEL_INSTRUCTION_BSAMPLE: case QANSEL_INSTRUCTION_BORN: case QANSEL_INSTRUCTION_BARRIER: case QANSEL_INSTRUCTION_PRINT: @@ -688,11 +692,76 @@ void qansel_get_barrier(QBytecode** qbc, int idx) exit(1); } -void qansel_born(cpx_mtx_t* stateVector, int PC, int qubitCount, unsigned char q0) +void qansel_born(QAnselContext* ctx, cpx_mtx_t* stateVector, int PC, int qubitCount, unsigned char q0, unsigned char mode) { unsigned int qubitCountPow2 = (unsigned int)pow(2, qubitCount); if (q0 == QANSEL_ALL_QUANTUM) { + float *psisquared = malloc(sizeof(float) * qubitCountPow2); + for (unsigned int j = 0; j < qubitCountPow2; j++) + { + if (mode == 0) + { + 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); + psisquared[j] = cpx_magsqr(&n); + if (mode == 0) + { + printf("\t%.2f%%\n", psisquared[j] * 100); + } + } + if (mode == 0) + { + free(psisquared); + return; + } + float *psisquared_sorted = malloc(sizeof(float) * qubitCountPow2); + unsigned short *sorting = malloc(sizeof(unsigned short) * qubitCountPow2); + for (int i = 0; i < qubitCountPow2; i++) psisquared_sorted[i] = 0; + for (int i = 0; i < qubitCountPow2; i++) + { + float max = -1; + int maxi = -1; + for (int j = 0; j < qubitCountPow2; j++) + { + if (psisquared[j] > max) + { + max = psisquared[j]; + maxi = j; + } + } + psisquared_sorted[i] = max; + sorting[i] = maxi; + psisquared[maxi] = -1; + } + free(psisquared); + unsigned short *stats = malloc(sizeof(unsigned short) * qubitCountPow2); + for (int i = 0; i < qubitCountPow2; i++) stats[i] = 0; + for (int i = 0; i < (ctx->bsampling_shots); i++) + { + float r = (ctx->hidden_variable) ? qansel_rand_h() : qansel_rand_t(ctx); + float j = 0; + for (unsigned int j = 0; j < qubitCountPow2; j++) + { + if (psisquared_sorted[j] >= r) + { + stats[j]++; + break; + } + r -= psisquared_sorted[j]; + if (j == qubitCountPow2 - 1) + { + stats[j]++; + } + } + } for (unsigned int j = 0; j < qubitCountPow2; j++) { unsigned int tmp = j; @@ -701,10 +770,11 @@ void qansel_born(cpx_mtx_t* stateVector, int PC, int qubitCount, unsigned char q putchar('0' + (tmp >> (qubitCount - 1) & 1)); tmp <<= 1; } - cpx_t n; - cpx_mtx_get(stateVector, 0, j, &n); - printf("\t%.1f%%\n", cpx_magsqr(&n) * 100); + printf("\t%i\t%.2f%%\n", stats[sorting[j]], ((float)stats[sorting[j]] / (float)(ctx->bsampling_shots)) * (float)100); } + free(psisquared_sorted); + free(stats); + free(sorting); } else if (q0 <= QANSEL_QBOUND_UPPER) { @@ -718,8 +788,21 @@ void qansel_born(cpx_mtx_t* stateVector, int PC, int qubitCount, unsigned char q prob += cpx_magsqr(&n); } } - printf("0\t%.1f%%\n", (1 - prob) * 100.0); - printf("1\t%.1f%%\n", prob * 100.0); + if (mode == 0) + { + printf("0\t%.2f%%\n", (1 - prob) * 100.0); + printf("1\t%.2f%%\n", prob * 100.0); + return; + } + + unsigned short stats = 0; + for (int i = 0; i < (ctx->bsampling_shots); i++) + { + float r = (ctx->hidden_variable) ? qansel_rand_h() : qansel_rand_t(ctx); + stats += r < prob ? 1 : 0; + } + printf("0\t%i\t%.2f%%\n", (ctx->bsampling_shots) - stats, (((float)(ctx->bsampling_shots) - (float)stats) / (float)(ctx->bsampling_shots)) * (float)100); + printf("1\t%i\t%.2f%%\n", stats, ((float)stats / (float)(ctx->bsampling_shots)) * (float)100); } } @@ -982,9 +1065,18 @@ int qansel_crawl(QAnselContext* ctx, unsigned char* program, int programSize, in if (qbitmax > *qubitCount) *qubitCount = qbitmax; PC += next; } - if (ctx->verbose) printf("Quantum bits allocated: %i\n", *qubitCount); - if (ctx->verbose) printf("Classical bits allocated: %i\n", *bitCount); - + if (*qubitCount > ctx->qubit_count) + { + fprintf(stderr, "QAnsel: Not enough qubits allocated.\n"); + return 0; + } + if (*bitCount > ctx->bit_count) + { + fprintf(stderr, "QAnsel: Not enough classical bits allocated.\n"); + return 0; + } + *qubitCount = ctx->qubit_count; + *bitCount = ctx->bit_count; return 1; } @@ -1401,7 +1493,10 @@ void qansel_run(QAnselContext* ctx, unsigned char* program, int programSize, int break; case QANSEL_INSTRUCTION_BORN: a0 = program[PC + 1]; - qansel_born(&stateVector, PC, qubitCount, a0); + qansel_born(ctx, &stateVector, PC, qubitCount, a0, 0); + case QANSEL_INSTRUCTION_BSAMPLE: + a0 = program[PC + 1]; + qansel_born(ctx, &stateVector, PC, qubitCount, a0, 1); break; case QANSEL_INSTRUCTION_DENSITY: a0 = program[PC + 1]; @@ -1546,14 +1641,14 @@ int qanselExecuteBytecode(unsigned char* buff, int sizeofbuff, QAnselContext* ct } if ((ctx->sampling_bit) == QANSEL_ALL) { - printf("\t%i\t%.1f%%\n", stats[i], ((float)stats[i] / (float)shots) * (float)100); + printf("\t%i\t%.2f%%\n", stats[i], ((float)stats[i] / (float)shots) * (float)100); } } if ((ctx->sampling_bit) != QANSEL_ALL) { float prob = ((float)count / (float)shots) * (float)100; - printf("0\t%i\t%.1f%%\n", shots-count, ((float)100)-prob); - printf("1\t%i\t%.1f%%\n", count, prob); + printf("0\t%i\t%.2f%%\n", shots-count, ((float)100)-prob); + printf("1\t%i\t%.2f%%\n", count, prob); } } else diff --git a/src/bytecode.h b/src/bytecode.h index a3da33f..71af0f2 100644 --- a/src/bytecode.h +++ b/src/bytecode.h @@ -129,7 +129,7 @@ unsigned char qansel_measure(QAnselContext* ctx, cpx_mtx_t* stateVector, unsigne int qansel_get_instruction_bitmax(unsigned char* ptr, int offset, int* bitmax, int* qbitmax); int qansel_get_instruction_size(unsigned char instr); void qansel_get_barrier(QBytecode** qbc, int idx); -void qansel_born(cpx_mtx_t* stateVector, int PC, int qubitCount, unsigned char q0); +void qansel_born(QAnselContext* ctx, cpx_mtx_t* stateVector, int PC, int qubitCount, unsigned char q0, unsigned char mode); void qansel_density_or_print(cpx_mtx_t* stateVector, unsigned char* bitVector, unsigned char density, int bitCount, int qubitCount, unsigned char a0); float qansel_get_float(unsigned char* program, int offset); short qansel_get_short(unsigned char* program, int offset); diff --git a/src/context.h b/src/context.h index ad4dc35..40374fb 100644 --- a/src/context.h +++ b/src/context.h @@ -16,6 +16,9 @@ typedef struct float hidden_variable; int display_delay; int sampling_shots; + int bsampling_shots; + int qubit_count; + int bit_count; FILE* random_file; } QAnselContext; diff --git a/src/gui.html b/src/gui.html index 5d45b2c..b0ac8d3 100644 --- a/src/gui.html +++ b/src/gui.html @@ -311,7 +311,7 @@ } else { - ret += "born q;\n"; + ret += "sample q;\n"; } } @@ -690,7 +690,14 @@ { if (mode == 1) { - err = err.replace(/[\n]/g, "
"); + try + { + err = err.replace(/[\n]/g, "
"); + } + catch + { + err = "Unknown server-side error."; + } } $(".program-instr")[0].style.display = "none"; $("#modal-main-confirm")[0].setAttribute("onclick", "closeModal();"); diff --git a/src/imports/istina-editor.js b/src/imports/istina-editor.js index 7d6bc2d..12a78e1 100644 --- a/src/imports/istina-editor.js +++ b/src/imports/istina-editor.js @@ -247,7 +247,8 @@ IstinaEditor.highlightForQAnsel = function(txt) "barrier", "hvar", "rand", - "born" + "born", + "bsample" ]; for (var i = 0; i < keywords.length; i++) diff --git a/src/openqasm.c b/src/openqasm.c index f71c81e..5104e0d 100644 --- a/src/openqasm.c +++ b/src/openqasm.c @@ -278,6 +278,7 @@ int qansel_process_chunk(int index, char* chunk, int line, regmatch_t* regmatche 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, "sample") == 0) instr = QANSEL_INSTRUCTION_BSAMPLE; 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; @@ -723,7 +724,7 @@ int qansel_process_chunks(char** chunks, int* associatedLines, int count, unsign { "^[ ]*qreg[ ]*q[ ]*\\[[ ]*([0-9][0-9]*)[ ]*\\][ ]*$", "^[ ]*creg[ ]*c[ ]*\\[[ ]*([0-9][0-9]*)[ ]*\\][ ]*$", - "^[ ]*(x|y|z|h|sdg|tdg|s|t|set|reset|barrier|born|density|print)[ ]*q[ ]*(\\[[ ]*([0-9][0-9]*)[ ]*\\][ ]*|)$", + "^[ ]*(x|y|z|h|sdg|tdg|s|t|set|reset|barrier|born|sample|density|print)[ ]*q[ ]*(\\[[ ]*([0-9][0-9]*)[ ]*\\][ ]*|)$", "^[ ]*(rx|ry|rz|u1)\\([ ]*([-/0-9PI.]*)[ ]*\\)[ ]*q[ ]*(\\[[ ]*([0-9][0-9]*)[ ]*\\][ ]*|)$", "^[ ]*(u2)\\([ ]*([-/0-9PI.]*)[ ]*,[ ]*([-/0-9PI.]*)[ ]*\\)[ ]*q[ ]*(\\[[ ]*([0-9][0-9]*)[ ]*\\][ ]*|)$", "^[ ]*(u|u3)\\([ ]*([-/0-9PI.]*)[ ]*,[ ]*([-/0-9PI.]*)[ ]*,[ ]*([-/0-9PI.]*)[ ]*\\)[ ]*q[ ]*(\\[[ ]*([0-9][0-9]*)[ ]*\\][ ]*|)$", @@ -778,6 +779,8 @@ int qansel_process_chunks(char** chunks, int* associatedLines, int count, unsign } *retBinary = binary; *retSize = binarySize; + ctx->qubit_count = qubitCount; + ctx->bit_count = bitCount; return status; } @@ -806,6 +809,7 @@ int qanselBuildFromSource(char* osource, unsigned char** binary, int* binarySize int status = qansel_read_script(source, &chunks, &chunksAssociatedLines, &chunksCount); int samplingshots = ctx->sampling_shots; ctx->sampling_shots = 0; + ctx->bsampling_shots = samplingshots == 0 ? QANSEL_SHOTS_DEFAULT : samplingshots; if (!status) { fprintf(stderr, "QAnsel: Read script failure.\n"); diff --git a/src/qansel.h b/src/qansel.h index c43f1c1..da84358 100644 --- a/src/qansel.h +++ b/src/qansel.h @@ -36,6 +36,7 @@ #define QANSEL_INSTRUCTION_MEASURE 0xD0 #define QANSEL_INSTRUCTION_DENSITY 0xD1 #define QANSEL_INSTRUCTION_BORN 0xD2 +#define QANSEL_INSTRUCTION_BSAMPLE 0xD3 #define QANSEL_INSTRUCTION_IF_E 0xE1 #define QANSEL_INSTRUCTION_IF_NE 0xE2 #define QANSEL_INSTRUCTION_IF_G 0xE3