From bb3c1193b8b5d45b597710913cbcc3a9b00ed0f0 Mon Sep 17 00:00:00 2001
From: miha-q <>
Date: Fri, 2 Aug 2024 17:23:16 -0400
Subject: [PATCH] Fri Aug 2 05:23:16 PM EDT 2024
---
examples/ghz.txt | 9 +--
src/bytecode.c | 121 +++++++++++++++++++++++++++++++----
src/bytecode.h | 2 +-
src/context.h | 3 +
src/gui.html | 11 +++-
src/imports/istina-editor.js | 3 +-
src/openqasm.c | 6 +-
src/qansel.h | 1 +
8 files changed, 131 insertions(+), 25 deletions(-)
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
--
2.39.5