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_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_RESET: return "QANSEL_INSTRUCTION_RESET";
case QANSEL_INSTRUCTION_BARRIER: return "QANSEL_INSTRUCTION_BARRIER";
case QANSEL_INSTRUCTION_EXIT: return "QANSEL_INSTRUCTION_EXIT";
}
{
return ((float)rand()) / ((float)RAND_MAX);
}
-float qansel_rand_t()
+float qansel_rand_t(QAnselContext* ctx)
{
- if (QANSEL_RANDOM_FILE)
+ if (ctx->hardware_rng != QANSEL_HARDWARE_NONE)
{
unsigned int num = 0;
for (unsigned char i = 0; i < 4; i++)
{
- num = (num << 8) | fgetc(QANSEL_RANDOM_FILE);
+ unsigned char r = 0;
+ switch (ctx->hardware_rng)
+ {
+ case QANSEL_HARDWARE_TRUERNG: r = fgetc(ctx->random_file); break;
+ case QANSEL_HARDWARE_RDSEED: r = qansel_hardware_rand(); break;
+ }
+ num = (num << 8) | r;
}
return ((float)num) / ((float)UINT32_MAX);
}
}
}
-float qansel_rand()
-{
- return QANSEL_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;
void qansel_instruction
(
+ QAnselContext* ctx,
cpx_mtx_t* stateVector,
int qubitCount,
unsigned char instr,
//us2 = get_time();
//printf("\tTranspose: %lu\n", us2 - us1);
#else
- if ((QANSEL_MODE & QANSEL_MODE_METAL) && !(QANSEL_MODE & QANSEL_MODE_THREADED) && tmp.cols >= 64)
+ if (((ctx->optimization_level) & QANSEL_MODE_METAL) && !((ctx->optimization_level) & QANSEL_MODE_THREADED) && tmp.cols >= 64)
{
cpx_mtx_knk_metal_2x2(tmp.ptr, filter.ptr, gate.ptr, filter.rows, filter.cols, gate.rows, gate.cols);
}
- else if ((QANSEL_MODE & QANSEL_MODE_THREADED) && tmp.cols >= 64)
+ else if (((ctx->optimization_level) & QANSEL_MODE_THREADED) && tmp.cols >= 64)
{
cpx_mtx_knk_threads_2x2(tmp.ptr, filter.ptr, gate.ptr, filter.rows, filter.cols, gate.rows, gate.cols);
}
us2 = get_time();
printf("\tBare: %lu\n", us2 - us1);
#else
- if ((QANSEL_MODE & QANSEL_MODE_METAL) && tmp.cols >= 64)
+ if (((ctx->optimization_level) & QANSEL_MODE_METAL) && tmp.cols >= 64)
{
cpx_mtx_dot_metal(tmp.ptr, stateVector->ptr, filter.ptr, stateVector->rows, stateVector->cols, filter.rows, filter.cols);
}
- else if ((QANSEL_MODE & QANSEL_MODE_THREADED) && tmp.cols >= 64)
+ else if (((ctx->optimization_level) & QANSEL_MODE_THREADED) && tmp.cols >= 64)
{
cpx_mtx_dot_threads(tmp.ptr, stateVector->ptr, filter.ptr, stateVector->rows, stateVector->cols, filter.rows, filter.cols);
}
if (needToFreeGate) free(gate_ptr);
}
-unsigned char qansel_measure(cpx_mtx_t* stateVector, unsigned char qubitCount, unsigned char qubit)
+unsigned char qansel_measure(QAnselContext* ctx, cpx_mtx_t* stateVector, unsigned char qubitCount, unsigned char qubit)
{
unsigned int qubitCountPow2 = (unsigned int)pow(2, qubitCount);
cpx_t n;
if (bit == 0) prob0 += cpx_magsqr(&n);
}
- float r = qansel_rand();
+ float r = (ctx->hidden_variable) ? qansel_rand_h() : qansel_rand_t(ctx);
unsigned char newBit = r < prob0 ? 0 : 1;
float probTot = 0;
for (unsigned int i = 0; i < qubitCountPow2; i++)
if (a0 > QANSEL_QBOUND_UPPER && a0 != QANSEL_ALL_QUANTUM) return 0;
if (a0 != QANSEL_ALL_QUANTUM) *qbitmax = a0 + 1;
return 1;
- case QANSEL_INSTRUCTION_SAMPLE:
case QANSEL_INSTRUCTION_IF_E:
case QANSEL_INSTRUCTION_IF_NE:
case QANSEL_INSTRUCTION_IF_G:
*qbitmax = a0 + 1;
*bitmax = (a1 - QANSEL_CBOUND_LOWER) + 1;
return 1;
- case QANSEL_INSTRUCTION_RAND:
- case QANSEL_INSTRUCTION_HVAR:
case QANSEL_INSTRUCTION_EXIT:
return 1;
}
return 0;
}
-int qansel_get_barrier(int** q, int qubitCount, int bitCount, unsigned char* binary, int pos)
+int qansel_get_instruction_size(unsigned char instr)
{
-
- unsigned char instr = binary[pos];
switch (instr)
{
- case QANSEL_INSTRUCTION_SAMPLE:
- case QANSEL_INSTRUCTION_RAND:
- case QANSEL_INSTRUCTION_HVAR:
+ 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_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_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_get_barrier(QBytecode** qbc, int idx)
+{
+ switch ((*qbc)[idx].op)
+ {
case QANSEL_INSTRUCTION_EXIT:
case QANSEL_INSTRUCTION_IF_E:
case QANSEL_INSTRUCTION_IF_NE:
case QANSEL_INSTRUCTION_IF_GE:
case QANSEL_INSTRUCTION_IF_L:
case QANSEL_INSTRUCTION_IF_LE:
- *q = NULL;
- return 0;
+ (*qbc)[idx].barrier_width = 0;
+ return;
case QANSEL_INSTRUCTION_X:
case QANSEL_INSTRUCTION_Y:
case QANSEL_INSTRUCTION_Z:
case QANSEL_INSTRUCTION_U1:
case QANSEL_INSTRUCTION_U2:
case QANSEL_INSTRUCTION_U3:
- //only barrier single-qubit instructions if
- // they are nexted in an if statement
- if (pos >= (1 + sizeof(unsigned short)))
- {
- switch (binary[pos - (1 + sizeof(unsigned short))])
- {
- 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:
- *q = malloc(1);
- (*q)[0] = binary[pos + 1] + QANSEL_QBOUND_LOWER;
- return 1;
- }
- }
- *q = NULL;
- return 0;
+ (*qbc)[idx].barrier_width = 1;
+ (*qbc)[idx].barrier[0] = (*qbc)[idx].bytes[1];
+ return;
case QANSEL_INSTRUCTION_MEASURE:
case QANSEL_INSTRUCTION_DENSITY:
- *q = malloc(2);
- (*q)[0] = binary[pos + 1] + QANSEL_QBOUND_LOWER;
- (*q)[1] = binary[pos + 2] + QANSEL_CBOUND_LOWER;
- return 1;
+ (*qbc)[idx].barrier_width = 2;
+ (*qbc)[idx].barrier[0] = (*qbc)[idx].bytes[1];
+ (*qbc)[idx].barrier[1] = (*qbc)[idx].bytes[2];
+ return;
case QANSEL_INSTRUCTION_BORN:
case QANSEL_INSTRUCTION_BARRIER:
case QANSEL_INSTRUCTION_PRINT:
case QANSEL_INSTRUCTION_RESET:
- switch (binary[pos + 1])
+ switch ((*qbc)[idx].bytes[1])
{
case QANSEL_ALL:
- *q = malloc(sizeof(int) * (qubitCount + bitCount));
- for (int i = 0; i < qubitCount; i++)
- {
- (*q)[i] = i + QANSEL_QBOUND_LOWER;
- }
- for (int i = 0; i < bitCount; i++)
- {
- (*q)[i] = i + QANSEL_CBOUND_LOWER;
- }
- return qubitCount + bitCount;
+ (*qbc)[idx].barrier_width = QANSEL_QUBITS_MAX * 2;
+ for (int i = 0; i < QANSEL_QUBITS_MAX; i++) (*qbc)[idx].barrier[i] = i;
+ for (int i = 0; i < QANSEL_QUBITS_MAX; i++) (*qbc)[idx].barrier[i] = i + QANSEL_CBOUND_LOWER;
+ return;
case QANSEL_ALL_QUANTUM:
- *q = malloc(sizeof(int) * qubitCount);
- for (int i = 0; i < qubitCount; i++)
- {
- (*q)[i] = i + QANSEL_QBOUND_LOWER;
- }
- return qubitCount;
+ (*qbc)[idx].barrier_width = QANSEL_QUBITS_MAX;
+ for (int i = 0; i < QANSEL_QUBITS_MAX; i++) (*qbc)[idx].barrier[i] = i;
+ return;
case QANSEL_ALL_CLASSIC:
- *q = malloc(sizeof(int) * bitCount);
- for (int i = 0; i < bitCount; i++)
- {
- (*q)[i] = i + QANSEL_CBOUND_LOWER;
- }
- return bitCount;
+ (*qbc)[idx].barrier_width = QANSEL_QUBITS_MAX;
+ for (int i = 0; i < QANSEL_QUBITS_MAX; i++) (*qbc)[idx].barrier[i] = i + QANSEL_CBOUND_LOWER;
+ return;
default:
- *q = malloc(1);
- (*q)[0] = binary[pos + 1];
- return 1;
+ (*qbc)[idx].barrier_width = 1;
+ (*qbc)[idx].barrier[0] = (*qbc)[idx].bytes[1];
+ return;
}
case QANSEL_INSTRUCTION_CX:
case QANSEL_INSTRUCTION_SWAP:
- *q = malloc(2);
- (*q)[0] = binary[pos + 1] + QANSEL_QBOUND_LOWER;
- (*q)[1] = binary[pos + 2] + QANSEL_QBOUND_LOWER;
- return 2;
+ (*qbc)[idx].barrier_width = 2;
+ (*qbc)[idx].barrier[0] = (*qbc)[idx].bytes[1];
+ (*qbc)[idx].barrier[1] = (*qbc)[idx].bytes[2];
+ return;
case QANSEL_INSTRUCTION_CCX:
case QANSEL_INSTRUCTION_CSWAP:
- *q = malloc(3);
- (*q)[0] = binary[pos + 1] + QANSEL_QBOUND_LOWER;
- (*q)[1] = binary[pos + 2] + QANSEL_QBOUND_LOWER;
- (*q)[2] = binary[pos + 3] + QANSEL_QBOUND_LOWER;
- return 3;
- }
- fprintf(stderr, "QAnsel (%04X): Unknown error in barrier analysis.\n", pos);
-}
-
-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;
+ (*qbc)[idx].barrier_width = 3;
+ (*qbc)[idx].barrier[0] = (*qbc)[idx].bytes[1];
+ (*qbc)[idx].barrier[1] = (*qbc)[idx].bytes[2];
+ (*qbc)[idx].barrier[2] = (*qbc)[idx].bytes[3];
+ return;
}
- return 0;
+ fprintf(stderr, "QAnsel (#%i): Unknown error in barrier analysis.\n", idx);
+ exit(1);
}
void qansel_born(cpx_mtx_t* stateVector, int PC, int qubitCount, unsigned char q0)
return ret;
}
-void qansel_reset(cpx_mtx_t* stateVector, unsigned char* bitVector, int qubitCount, int bitCount, unsigned char q0)
+void qansel_reset(QAnselContext* ctx, cpx_mtx_t* stateVector, unsigned char* bitVector, int qubitCount, int bitCount, unsigned char q0)
{
unsigned int qubitCountPow2 = (unsigned int)pow(2, qubitCount);
if (q0 == QANSEL_ALL)
}
else if (q0 <= QANSEL_QBOUND_UPPER)
{
- unsigned char bit = qansel_measure(stateVector, qubitCount, q0);
+ unsigned char bit = qansel_measure(ctx, stateVector, qubitCount, q0);
if (bit)
{
- qansel_instruction(stateVector, qubitCount, QANSEL_INSTRUCTION_X, q0, 0, 0, 0, NULL);
+ qansel_instruction(ctx, stateVector, qubitCount, QANSEL_INSTRUCTION_X, q0, 0, 0, 0, NULL);
}
}
else if (q0 >= QANSEL_CBOUND_LOWER && q0 <= QANSEL_CBOUND_UPPER)
return ret;
}
-int qansel_crawl(unsigned char* program, int programSize, int* qubitCount, int* bitCount, int* sample)
+//computes program efficiency
+// points are awarded for how long strings of single qubit
+// instructions are
+int qansel_efficiency(QBytecode* program, int programSize, int head)
{
- if (QANSEL_VERBOSE) printf("Crawling program . . .\n");
+ int score = 0;
+ int tmpscore = 0;
+ int idx = head;
+
+ for (int i = 0; i < programSize; i++)
+ {
+ switch (program[idx].op)
+ {
+ 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:
+ switch (tmpscore)
+ {
+ case 0: tmpscore = 1; break;
+ default: tmpscore *= 2;
+ }
+ break;
+ 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:
+ break;
+ default:
+ if (tmpscore > 1) score += tmpscore;
+ tmpscore = 0;
+ }
+ idx = program[idx].next;
+ }
+ return score;
+}
+
+int qansel_crawl(QAnselContext* ctx, unsigned char* program, int programSize, int* qubitCount, int* bitCount)
+{
+ if (ctx->verbose) printf("Crawling program . . .\n");
int PC = 0;
*qubitCount = 0;
*bitCount = 0;
- *sample = QANSEL_ALL;
while (PC < programSize)
{
int next = qansel_get_instruction_size(program[PC]);
- if (program[PC] == QANSEL_INSTRUCTION_SAMPLE)
- {
- if ((program[PC + 1] < QANSEL_CBOUND_LOWER || program[PC + 1] > QANSEL_CBOUND_UPPER) && program[PC + 1] != QANSEL_ALL_CLASSIC)
- {
- if (QANSEL_VERBOSE) fprintf(stderr, "QAnsel (%04X): Invalid index.\n", PC);
- }
- else
- {
- *sample = program[PC + 1] - QANSEL_CBOUND_LOWER;
- }
- }
if (next == 0)
{
printf("QAnsel (%04X): Invalid instruction 0x%02x.\n", PC, program[PC]);
if (qbitmax > *qubitCount) *qubitCount = qbitmax;
PC += next;
}
- if (QANSEL_VERBOSE) printf("Quantum bits allocated: %i\n", *qubitCount);
- if (QANSEL_VERBOSE) printf("Classical bits allocated: %i\n", *bitCount);
+ if (ctx->verbose) printf("Quantum bits allocated: %i\n", *qubitCount);
+ if (ctx->verbose) printf("Classical bits allocated: %i\n", *bitCount);
+
return 1;
}
-void qansel_run(unsigned char* program, int programSize, int qubitCount, int bitCount, unsigned char* outputBitVector)
+void qansel_reorder(QAnselContext* ctx, unsigned char* program, int programSize)
{
- int useQueue = (QANSEL_MODE & QANSEL_MODE_QUEUE) ? 1 : 0;
+ if (ctx->verbose) printf("Reordering . . .\n");
+
+ //break out program for easier manipulation
+ QBytecode* ramInstr = malloc(0);
+ int ramInstrLen = 0;
+ int copyifop = 0;
+ unsigned char ifop[16];
+ int PC = 0;
+
+ while (PC < programSize)
+ {
+ int next = qansel_get_instruction_size(program[PC]);
+ switch (program[PC])
+ {
+ 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:
+ memcpy(ifop, program + PC, next);
+ copyifop = 1;
+ PC += next;
+ continue;
+ }
+ ramInstr = realloc(ramInstr, sizeof(QBytecode) * (ramInstrLen + 1));
+ ramInstr[ramInstrLen].size = next;
+ memcpy(ramInstr[ramInstrLen].bytes, program + PC, next);
+ ramInstr[ramInstrLen].op = program[PC];
+ ramInstr[ramInstrLen].use_ifop = copyifop;
+ if (copyifop)
+ {
+ memcpy(ramInstr[ramInstrLen].ifop, ifop, sizeof(ifop));
+ copyifop = 0;
+ }
+ ramInstrLen++;
+ PC += next;
+ }
+ for (int i = 0; i < ramInstrLen; i++)
+ {
+ if (i == 0)
+ {
+ ramInstr[0].prev = -1;
+ ramInstr[0].next = ramInstrLen > 1 ? 1 : -1;
+ }
+ else if (i == ramInstrLen - 1)
+ {
+ ramInstr[ramInstrLen - 1].prev = i - 1;
+ ramInstr[ramInstrLen - 1].next = -1;
+ }
+ else
+ {
+ ramInstr[i].prev = i - 1;
+ ramInstr[i].next = i + 1;
+ }
+ //we can only rearrange single-qubit instructions
+ // so treat other instructions as pre-checked
+ switch (ramInstr[i].op)
+ {
+ 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:
+ ramInstr[i].checked = 0;
+ break;
+ default: ramInstr[i].checked = 1;
+ }
+ }
+
+ for (int i = 0; i < ramInstrLen; i++)
+ {
+ qansel_get_barrier(&ramInstr, i);
+ }
+
+ QBytecode* reordered[2];
+ reordered[0] = malloc(ramInstrLen * sizeof(QBytecode));
+ reordered[1] = malloc(ramInstrLen * sizeof(QBytecode));
+ memcpy(reordered[0], ramInstr, ramInstrLen * sizeof(QBytecode));
+ memcpy(reordered[1], ramInstr, ramInstrLen * sizeof(QBytecode));
+
+ int efficiency = qansel_efficiency(ramInstr, ramInstrLen, 0);
+ int head[2];
+ head[0] = 0;
+ head[1] = 0;
+ for (int reorid = 0; reorid < 2; reorid++)
+ {
+ while (1)
+ {
+ //find the next unchecked instruction
+ int found = -1;
+ int idx = head[reorid];
+ for (int i = 0; i < ramInstrLen; i++)
+ {
+ if (reordered[reorid][idx].checked == 0)
+ {
+ found = idx;
+ break;
+ }
+ idx = reordered[reorid][idx].next;
+ }
+ if (found == -1) break;
+ //check if it can be moved up
+ reordered[reorid][found].checked = 1;
+ int blocked = 0;
+ idx = reordered[reorid][idx].prev;
+ while (idx != -1)
+ {
+ for (int i = 0; i < reordered[reorid][idx].barrier_width; i++)
+ {
+ //verify no classical bit barrier
+ if (reordered[reorid][found].use_ifop)
+ {
+ switch (reordered[reorid][found].ifop[1])
+ {
+ case QANSEL_ALL_CLASSIC:
+ case QANSEL_ALL:
+ blocked = 1;
+ break;
+ default:
+ if (reordered[reorid][found].ifop[1] == reordered[reorid][idx].barrier[i])
+ blocked = 1;
+ }
+ if (blocked) break;
+ }
+ //verify no quantum bit barrier
+ if (reordered[reorid][found].bytes[1] == reordered[reorid][idx].barrier[i])
+ {
+ blocked = 1;
+ break;
+ }
+ }
+ if (blocked) break;
+ idx = reordered[reorid][idx].prev;
+ }
+ if (reordered[reorid][found].prev != idx)
+ {
+ QBytecode* tmpbc = malloc(ramInstrLen * sizeof(QBytecode));
+ memcpy(tmpbc, reordered[reorid], ramInstrLen * sizeof(QBytecode));
+ reordered[reorid][ reordered[reorid][found].prev ].next = reordered[reorid][found].next;
+ if (reordered[reorid][found].next != -1)
+ {
+ reordered[reorid][ reordered[reorid][found].next ].prev = reordered[reorid][found].prev;
+ }
+
+ if (idx == -1)
+ {
+ reordered[reorid][head[reorid]].prev = found;
+ reordered[reorid][found].next = head[reorid];
+ reordered[reorid][found].prev = -1;
+ head[reorid] = found;
+ }
+ else
+ {
+ reordered[reorid][ reordered[reorid][idx].next ].prev = found;
+ reordered[reorid][found].next = reordered[reorid][idx].next;
+ reordered[reorid][found].prev = idx;
+ reordered[reorid][idx].next = found;
+ }
+ if (reorid == 1)
+ {
+ int tmpeff = qansel_efficiency(reordered[reorid], ramInstrLen, head[reorid]);
+ if (tmpeff >= efficiency)
+ {
+ efficiency = tmpeff;
+ }
+ else
+ {
+ memcpy(reordered[reorid], tmpbc, ramInstrLen * sizeof(QBytecode));
+ }
+ }
+ free(tmpbc);
+ }
+ }
+ }
+
+ efficiency = qansel_efficiency(ramInstr, ramInstrLen, 0);
+ int best = -1;
+ int besti = -1;
+ for (int i = 0; i < 2; i++)
+ {
+ int tmpeff = qansel_efficiency(reordered[i], ramInstrLen, head[i]);
+ if (tmpeff > best)
+ {
+ besti = i;
+ best = tmpeff;
+ }
+ }
+ if (best > efficiency)
+ {
+ memcpy(ramInstr, reordered[besti], ramInstrLen * sizeof(QBytecode));
+ }
+ for (int i = 0; i < 2; i++)
+ {
+ free(reordered[i]);
+ }
+
+ int copyloc = 0;
+ for (int i = 0; i < ramInstrLen; i++)
+ {
+ int next;
+ if (ramInstr[i].use_ifop)
+ {
+ next = qansel_get_instruction_size(ramInstr[i].ifop[0]);
+ memcpy(program + copyloc, ramInstr[i].ifop, next);
+ copyloc += next;
+ }
+ next = qansel_get_instruction_size(ramInstr[i].op);
+ memcpy(program + copyloc, ramInstr[i].bytes, next);
+ copyloc += next;
+ }
+
+ if (ctx->verbose)
+ {
+ if (best > efficiency)
+ {
+ printf("Efficiency score increased from %i to %i.\n", efficiency, best);
+ }
+ else
+ {
+ printf("Could not increase efficiency.\n");
+ }
+ }
+}
+
+void qansel_run(QAnselContext* ctx, unsigned char* program, int programSize, int qubitCount, int bitCount, unsigned char* outputBitVector)
+{
+ int useQueue = ((ctx->optimization_level) & QANSEL_MODE_QUEUE) ? 1 : 0;
int PC = 0;
unsigned int qubitCountPow2 = (unsigned int)pow(2, qubitCount);
unsigned char bitVector[bitCount];
queueVector[i].cols = 2;
}
}
- if (QANSEL_USE_DISPLAY) { QANSEL_USE_DISPLAY = display(&stateVector, qubitCount, QANSEL_USE_DISPLAY); }
+ if (ctx->display_delay) { ctx->display_delay = display(&stateVector, qubitCount, ctx->display_delay); }
unsigned char skip = 0, a0 = 0, a1 = 0, a2 = 0;
unsigned char flags = 0;
unsigned short tmp = 0;
case QANSEL_INSTRUCTION_IF_GE:
case QANSEL_INSTRUCTION_IF_L:
case QANSEL_INSTRUCTION_IF_LE:
- case QANSEL_INSTRUCTION_SAMPLE:
- case QANSEL_INSTRUCTION_HVAR:
- case QANSEL_INSTRUCTION_RAND:
break;
default:
- qansel_instruction(&stateVector, qubitCount, instr, 0, 0, 0, 0, &queueVector);
+ qansel_instruction(ctx, &stateVector, qubitCount, instr, 0, 0, 0, 0, &queueVector);
for (int i = 0; i < qubitCount; i++)
{
memcpy(queueVector[i].ptr, Identity, sizeof(Identity));
}
a0 = program[PC + 1];
if (useQueue) qansel_instruction_queue(&queueVector, qubitCount, instr, a0, f0, f1, f2);
- else qansel_instruction(&stateVector, qubitCount, instr, a0, f0, f1, f2, NULL);
+ else qansel_instruction(ctx, &stateVector, qubitCount, instr, a0, f0, f1, f2, NULL);
break;
case QANSEL_INSTRUCTION_CX:
a0 = program[PC + 1];
case QANSEL_INSTRUCTION_MEASURE:
a0 = program[PC + 1];
a1 = program[PC + 2] - QANSEL_CBOUND_LOWER;
- bitVector[a1] = qansel_measure(&stateVector, qubitCount, a0);
+ bitVector[a1] = qansel_measure(ctx, &stateVector, qubitCount, a0);
break;
case QANSEL_INSTRUCTION_BORN:
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:
- QANSEL_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:
- QANSEL_HIDDEN_VARIABLE = 0;
+ qansel_reset(ctx, &stateVector, bitVector, qubitCount, bitCount, a0);
break;
case QANSEL_INSTRUCTION_IF_E:
a0 = program[PC + 1];
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 (QANSEL_USE_DISPLAY) { QANSEL_USE_DISPLAY = display(&stateVector, qubitCount, QANSEL_USE_DISPLAY); }
+ if (ctx->display_delay) { ctx->display_delay = display(&stateVector, qubitCount, ctx->display_delay); }
}
if (outputBitVector != NULL)
{
}
free(queueVector);
}
- if (QANSEL_USE_DISPLAY) { display(NULL, 0, 0); }
+ if (ctx->display_delay) { display(NULL, 0, 0); }
}
-int qanselExecuteBytecode(unsigned char* buff, int sizeofbuff)
+int qanselExecuteBytecode(unsigned char* buff, int sizeofbuff, QAnselContext* ctx)
{
+ if (!qanselContextValidate(ctx)) return 0;
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
float seed = (float)((unsigned long)ts.tv_sec * 1000000000LL + ts.tv_nsec);
qansel_rand_s(seed);
+ if (ctx != NULL && ctx->hidden_variable != 0)
+ {
+ unsigned int tmp;
+ memcpy(&tmp, &(ctx->hidden_variable), sizeof(unsigned int));
+ srand(tmp);
+ }
+
unsigned short vals;
float valf;
int pos = 0;
- int qubitCount, bitCount, sample;
- if (!qansel_crawl(buff, sizeofbuff, &qubitCount, &bitCount, &sample))
+ int qubitCount, bitCount;
+ if (!qansel_crawl(ctx, buff, sizeofbuff, &qubitCount, &bitCount))
{
return 0;
}
- if (sample != QANSEL_ALL)
+ if (ctx != NULL && ctx->sampling_shots > 0)
{
unsigned short stats[65536];
for (unsigned int i = 0; i < (1 << bitCount); i++)
unsigned char bitVect[bitCount];
memset(bitVect, 0, bitCount);
for (int i = 0; i < bitCount; i++) bitVect[i] = 0;
- unsigned int shots = QANSEL_SAMPLE_COUNT;
+ unsigned int shots = ctx->sampling_shots;
for (unsigned int i = 0; i < shots; i++)
{
- qansel_run(buff, sizeofbuff, qubitCount, bitCount, bitVect);
+ qansel_run(ctx, buff, sizeofbuff, qubitCount, bitCount, bitVect);
unsigned short stat = 0;
for (signed char j = bitCount - 1; j >= 0; j--)
{
for (unsigned char j = 0; j < bitCount; j++)
{
unsigned char bit = (tmp >> (bitCount - 1) & 1);
- if (j == (bitCount - sample - 1) && bit)
+ if (j == (bitCount - (ctx->sampling_bit) - 1) && bit)
{
count += stats[i];
}
- if (sample == QANSEL_ALL_QUANTUM)
+ if ((ctx->sampling_bit) == QANSEL_ALL)
{
putchar('0' + bit);
}
tmp <<= 1;
}
- if (sample == QANSEL_ALL_QUANTUM)
+ if ((ctx->sampling_bit) == QANSEL_ALL)
{
printf(": %.1f%%\n", ((float)stats[i] / (float)shots) * (float)100);
}
}
- if (sample != QANSEL_ALL_QUANTUM)
+ if ((ctx->sampling_bit) != QANSEL_ALL)
{
float prob = ((float)count / (float)shots) * (float)100;
printf("0: %.1f%%\n", ((float)100)-prob);
}
else
{
- qansel_run(buff, sizeofbuff, qubitCount, bitCount, NULL);
+ qansel_run(ctx, buff, sizeofbuff, qubitCount, bitCount, NULL);
}
return 1;
}
#ifndef __cpx__
#define __cpx__
-#include <stdint.h>
-#include <stddef.h>
-#include <math.h>
-#include <pthread.h>
-#include <string.h>
-#include "hardware.c"
-#include "kernel_cpu.cl"
-#include "kernel_gpu.cl"
typedef struct
{
float real, imaginary;
int rows, cols;
} cpx_mtx_t;
-uint8_t* cpx_str(cpx_t* n)
+unsigned char* cpx_str(cpx_t* n)
{
- uint8_t* r;
+ unsigned char* r;
int z;
float rl = n->real;
}
else
{
- uint8_t op = n->imaginary >= 0 ? '+' : '-';
+ unsigned char op = n->imaginary >= 0 ? '+' : '-';
z = snprintf(NULL, 0, "%f %c %fi", rl, op, ig);
r = malloc(z + 1);
sprintf(r, "%f %c %fi", rl, op, ig);
{
cpx_t n;
cpx_mtx_get(m, r, c, &n);
- uint8_t* s = cpx_str(&n);
+ unsigned char* s = cpx_str(&n);
if (c > 0) printf(", ");
printf("%s", s);
free(s);
void cpx_mtx_knk_threads(float* ptrR, float* ptrA, float* ptrB, int rowsA, int colsA, int rowsB, int colsB)
{
int delimeter = rowsA * rowsB;
- int cores = get_core_count();
+ int cores = qansel_get_core_count();
int threadCount = cores;
if (threadCount > delimeter) threadCount = delimeter;
int delimetersPerThread = delimeter / threadCount;
exit(1);
}
}
- for (uint32_t i = 0; i < threadCount; i++)
+ for (unsigned int i = 0; i < threadCount; i++)
{
if (pthread_join(threads[i], NULL))
{
void cpx_mtx_knk_threads_2x2(float* ptrR, float* ptrA, float* ptrB, int rowsA, int colsA, int rowsB, int colsB)
{
int delimeter = (rowsA * rowsB) / 2;
- int cores = get_core_count();
+ int cores = qansel_get_core_count();
int threadCount = cores;
if (threadCount > delimeter) threadCount = delimeter;
int delimetersPerThread = delimeter / threadCount;
exit(1);
}
}
- for (uint32_t i = 0; i < threadCount; i++)
+ for (unsigned int i = 0; i < threadCount; i++)
{
if (pthread_join(threads[i], NULL))
{
void cpx_mtx_dot_threads(float* ptrR, float* ptrA, float* ptrB, int rowsA, int colsA, int rowsB, int colsB)
{
int delimeter = colsB;
- int cores = get_core_count();
+ int cores = qansel_get_core_count();
int threadCount = cores;
if (threadCount > delimeter) threadCount = delimeter;
int delimeterPerThread = delimeter / threadCount;
exit(1);
}
}
- for (uint32_t i = 0; i < threadCount; i++)
+ for (unsigned int i = 0; i < threadCount; i++)
{
if (pthread_join(threads[i], NULL))
{
}
-uint8_t cpx_mtx_begin()
+unsigned char cpx_mtx_begin(unsigned char verbose)
{
cl_uint count;
cl_int err;
if (err != CL_SUCCESS || count == 0)
{
if (err == 0)
- fprintf(stderr, "GPU error: No supported platforms found.\n");
+ fprintf(stderr, "QAnsel (GPU): No supported platforms found.\n");
else
- fprintf(stderr, "GPU error: clGetPlatformIDs() failed.\n");
+ fprintf(stderr, "QAnsel (GPU): clGetPlatformIDs() failed.\n");
return 0;
}
if (err != CL_SUCCESS || count == 0)
{
if (count == 0)
- fprintf(stderr, "GPU error: No supported GPUs found.\n");
+ fprintf(stderr, "QAnsel (GPU): No supported GPUs found.\n");
else
- fprintf(stderr, "GPU error: clGetDeviceIDs() failed.\n");
+ fprintf(stderr, "QAnsel (GPU): clGetDeviceIDs() failed.\n");
return 0;
}
- //size_t size;
- //clGetDeviceInfo(cpx_mtx_device_id, CL_DEVICE_NAME, 0, NULL, &size);
- //char str[size];
- //clGetDeviceInfo(cpx_mtx_device_id, CL_DEVICE_NAME, size, str, NULL);
- //printf("%s\n", str);
+ size_t size;
+ err = clGetDeviceInfo(cpx_mtx_device_id, CL_DEVICE_NAME, 0, NULL, &size);
+ if (err != CL_SUCCESS)
+ {
+ fprintf(stderr, "QAnsel: Unknown GPU error.\n");
+ return 0;
+ }
+ char str[size];
+ err = clGetDeviceInfo(cpx_mtx_device_id, CL_DEVICE_NAME, size, str, NULL);
+ if (err != CL_SUCCESS)
+ {
+ fprintf(stderr, "QAnsel: Unknown GPU error.\n");
+ return 0;
+ }
+ if (verbose) printf("QAnsel: Hardware `%s` selected.\n", str);
cpx_mtx_context = clCreateContext(NULL, 1, &cpx_mtx_device_id, NULL, NULL, &err);
if (err != CL_SUCCESS)
{
- fprintf(stderr, "GPU error: clCreateContext() failed.\n");
+ fprintf(stderr, "QAnsel (GPU): clCreateContext() failed.\n");
return 0;
}
cpx_mtx_command_queue = clCreateCommandQueue(cpx_mtx_context, cpx_mtx_device_id, 0, &err);
if (err != CL_SUCCESS)
{
- fprintf(stderr, "GPU error: clCreateCommandQueue() failed.\n");
+ fprintf(stderr, "QAnsel (GPU): clCreateCommandQueue() failed.\n");
err = clReleaseContext(cpx_mtx_context);
if (err != CL_SUCCESS)
- fprintf(stderr, "GPU error: clReleaseContext() failed.\n");
+ fprintf(stderr, "QAnsel (GPU): clReleaseContext() failed.\n");
return 0;
}
return 1;
err = clReleaseCommandQueue(cpx_mtx_command_queue);
if (err != CL_SUCCESS)
{
- fprintf(stderr, "GPU error: clReleaseCommandQueue() failed.\n");
+ fprintf(stderr, "QAnsel (GPU): clReleaseCommandQueue() failed.\n");
}
err = clReleaseContext(cpx_mtx_context);
if (err != CL_SUCCESS)
{
- fprintf(stderr, "GPU error: clReleaseContext() failed.\n");
+ fprintf(stderr, "QAnsel (GPU): clReleaseContext() failed.\n");
}
free(cpx_mtx_cache);
}
exit(1);
}
}
- for (uint32_t i = 0; i < threadCount; i++)
+ for (unsigned int i = 0; i < threadCount; i++)
{
if (pthread_join(threads[i], NULL))
{
cl_mem memR = clCreateBuffer(cpx_mtx_context, CL_MEM_WRITE_ONLY, sizeR, NULL, &err); gpuerr(err);
//Populate buffers
- unsigned long long int q = get_time();
+ unsigned long long int q = qansel_get_time();
err = clEnqueueWriteBuffer(cpx_mtx_command_queue, memA, CL_TRUE, 0, sizeA, ptrA, 0, NULL, NULL);
gpuerr(err);
err = clEnqueueWriteBuffer(cpx_mtx_command_queue, memB, CL_TRUE, 0, sizeB, ptrB, 0, NULL, NULL);