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, "<br />");
+				try
+				{
+					err = err.replace(/[\n]/g, "<br />");
+				}
+				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