diff --git a/python/quantum-pecos/src/pecos/engines/cvm/classical.py b/python/quantum-pecos/src/pecos/engines/cvm/classical.py index 606942f80..74d5c75bf 100644 --- a/python/quantum-pecos/src/pecos/engines/cvm/classical.py +++ b/python/quantum-pecos/src/pecos/engines/cvm/classical.py @@ -156,6 +156,7 @@ def get_val( a: BinArray | tuple[str, int] | list[str | int] | str | int, output: dict[str, BinArray], width: int, + shot_id: int, ) -> BinArray: """Extract and convert a value to BinArray. @@ -166,6 +167,7 @@ def get_val( a: Value to extract - can be BinArray, variable reference, or literal. output: Dictionary containing variable values. width: Bit width for value conversion. + shot_id: The current instance's shot id Returns: Value converted to BinArray format. @@ -181,7 +183,7 @@ def get_val( val = output[sym][idx] elif isinstance(a, str): - val = int(output[a]) + val = shot_id if a == "JOB_shotnum" else int(output[a]) elif isinstance(a, int): val = a @@ -197,6 +199,7 @@ def recur_eval_op( expr_dict: dict[str, Any], output: dict[str, BinArray], width: int, + shot_id: int, ) -> BinArray: """Recursively evaluate a nested expression dictionary. @@ -207,6 +210,7 @@ def recur_eval_op( expr_dict: Dictionary containing expression with 'op', 'a', 'b', 'c' keys. output: Dictionary containing variable values. width: Bit width for operations. + shot_id: The current instance's shot id. Returns: Result of the evaluated expression as BinArray. @@ -223,19 +227,19 @@ def recur_eval_op( c = ( recur_eval_op(c, output, width) if isinstance(c, dict) - else get_val(c, output, width) + else get_val(c, output, width, shot_id) ) - a = eval_op(op, c, width=width) + a = eval_op(op, c, width=width, shot_id=shot_id) else: - a = get_val(a, output, width) + a = get_val(a, output, width, shot_id) if b: b = ( recur_eval_op(b, output, width) if isinstance(b, dict) - else get_val(b, output, width) + else get_val(b, output, width, shot_id) ) a = eval_op(op, a, b, width=width) @@ -247,6 +251,7 @@ def eval_cop( cop_expr: dict[str, Any] | list[dict[str, Any]], output: dict[str, BinArray], width: int, + shot_id: int, ) -> None: """Evaluate classical operation expression. @@ -280,7 +285,7 @@ def eval_cop( # Eval assignment # --------------- - expr_eval = recur_eval_op(cop_expr, output, width) + expr_eval = recur_eval_op(cop_expr, output, width, shot_id) # Assign the final value: # ----------------------- diff --git a/python/quantum-pecos/src/pecos/engines/hybrid_engine_old.py b/python/quantum-pecos/src/pecos/engines/hybrid_engine_old.py index e359db739..87cd1d9b1 100644 --- a/python/quantum-pecos/src/pecos/engines/hybrid_engine_old.py +++ b/python/quantum-pecos/src/pecos/engines/hybrid_engine_old.py @@ -262,7 +262,12 @@ def run_circuit( eval_cfunc(self, params, output) elif params.get("expr"): - eval_cop(params.get("expr"), output, width=self.regwidth) + eval_cop( + params.get("expr"), + output, + width=self.regwidth, + shot_id=self.rng_model.shot_id, + ) elif params.get("cop_type") == "ExportCVar": sym = params["export"] diff --git a/python/tests/pecos/regression/test_qasm/regression_qasm/Job_shotnum_usage.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/Job_shotnum_usage.qasm new file mode 100644 index 000000000..eb4cfcc78 --- /dev/null +++ b/python/tests/pecos/regression/test_qasm/regression_qasm/Job_shotnum_usage.qasm @@ -0,0 +1,8 @@ +OPENQASM 2.0; +include "hqslib1.inc"; +qreg q[1]; +creg c[1]; +creg shotnum[32]; +U1q(0.5*pi,0.5*pi) q[0]; +shotnum = JOB_shotnum; +measure q[0] -> c[0]; diff --git a/python/tests/pecos/regression/test_qasm/regression_qasm/RNGnum_h5.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/RNGnum_h5.qasm new file mode 100644 index 000000000..d42323157 --- /dev/null +++ b/python/tests/pecos/regression/test_qasm/regression_qasm/RNGnum_h5.qasm @@ -0,0 +1,91 @@ +OPENQASM 2.0; +include "qelib1.inc"; +qreg q[5]; +creg c[5]; + +creg cond0[32]; +creg hgates0[4]; + +creg cond1[32]; +creg hgates1[4]; + +creg rand_seed[64]; +creg rand_bound[32]; +creg rand_index[32]; +creg cond2[32]; +creg hgates2[4]; + + +///////////////////////////////////////////// +// Test RNG functions using cbit arguments +///////////////////////////////////////////// + +RNGseed(rand_seed[0]); +RNGbound(rand_bound[0]); +RNGindex(rand_index[0]); + +cond0 = RNGnum(); + +h q; +hgates0[0] = 1; + +if (cond0[0] != 0) h q; +if (cond0[0] != 0) hgates0[1] = 1; + +if (cond0[1] != 0) h q; +if (cond0[1] != 0) hgates0[2] = 1; + +if (cond0[3] != 0) h q; +if (cond0[3] != 0) hgates0[3] = 1; + +/////////////////////// +////////////////////// +// Test RNG functions using integer arguments +///////////////////////////////////////////// + +RNGseed(1000); +RNGbound(16); +RNGindex(4); + +cond1 = RNGnum(); + +h q; +hgates1[0] = 1; + +if (cond1[0] != 0) h q; +if (cond1[0] != 0) hgates1[1] = 1; + +if (cond1[1] != 0) h q; +if (cond1[1] != 0) hgates1[2] = 1; + +if (cond1[3] != 0) h q; +if (cond1[3] != 0) hgates1[3] = 1; + +///////////////////////////////////////////// +// Test RNG functions using creg arguments +///////////////////////////////////////////// + +rand_seed = 2000; +rand_bound = 32; +rand_index = 8; + +RNGseed(rand_seed); +RNGbound(rand_bound); +RNGindex(rand_index); + +cond2 = RNGnum(); + +h q; +hgates2[0] = 1; + +if (cond2[0] != 0) h q; +if (cond2[0] != 0) hgates2[1] = 1; + +if (cond2[1] != 0) h q; +if (cond2[1] != 0) hgates2[2] = 1; + +if (cond2[3] != 0) h q; +if (cond2[3] != 0) hgates2[3] = 1; + + +measure q->c; diff --git a/python/tests/pecos/regression/test_qasm/regression_qasm/RNGnum_jobvar_h5.qasm b/python/tests/pecos/regression/test_qasm/regression_qasm/RNGnum_jobvar_h5.qasm new file mode 100644 index 000000000..386253c88 --- /dev/null +++ b/python/tests/pecos/regression/test_qasm/regression_qasm/RNGnum_jobvar_h5.qasm @@ -0,0 +1,32 @@ +OPENQASM 2.0; +include "qelib1.inc"; +qreg q[5]; +creg c[5]; + +creg cond1[32]; +creg hgates1[4]; + +///////////////////////////////////////////// +// Test RNG functions with jobvar index +///////////////////////////////////////////// + +RNGseed(1000); +RNGbound(16); +RNGindex(JOB_shotnum); + +h q; +hgates1[0] = 1; + +cond1 = RNGnum(); +if (cond1[0] != 0) h q; +if (cond1[0] != 0) hgates1[1] = 1; + +cond1 = RNGnum(); +if (cond1[1] != 0) h q; +if (cond1[1] != 0) hgates1[2] = 1; + +cond1 = RNGnum(); +if (cond1[3] != 0) h q; +if (cond1[3] != 0) hgates1[3] = 1; + +measure q->c;