From 13456ee413dcd02dfdc476ccb8898c52399420a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E5=AE=9A=E4=B8=9C?= <3081545786@qq.com> Date: Fri, 15 Mar 2024 17:19:14 +0800 Subject: [PATCH 01/13] =?UTF-8?q?=F0=9F=90=9E=20fix:=20fix=20unittest?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix unittest and add qualesim. --- setup.cfg | 4 + src/quingo/backend/backend_hub.py | 14 +-- src/quingo/backend/qualesim_quantumsim.py | 118 +++++++++++----------- unittest/test_backends.py | 25 ++--- 4 files changed, 83 insertions(+), 78 deletions(-) diff --git a/setup.cfg b/setup.cfg index a495744..f2849ce 100644 --- a/setup.cfg +++ b/setup.cfg @@ -30,6 +30,10 @@ install_requires = requests tqdm pyezq + qualesim + qualesim-quiets + qualesim-quantumsim + qualesim-qcis [options.packages.find] where = src \ No newline at end of file diff --git a/src/quingo/backend/backend_hub.py b/src/quingo/backend/backend_hub.py index 46ca22e..234cb77 100755 --- a/src/quingo/backend/backend_hub.py +++ b/src/quingo/backend/backend_hub.py @@ -10,7 +10,7 @@ class BackendType(enum.Enum): QUANTIFY = enum.auto() XIAOHONG = enum.auto() # QUALESIM_TEQUILA = enum.auto() - # QUALESIM_QUANTUMSIM = enum.auto() + QUALESIM_QUANTUMSIM = enum.auto() def singleton(cls): @@ -64,12 +64,12 @@ class Backend_hub: # True, # Qisa.QCIS, # ), - # BackendType.QUALESIM_QUANTUMSIM: ( - # "QuaLeSim_quantumsim", - # "qualesim_quantumsim", - # True, - # Qisa.QCIS, - # ), + BackendType.QUALESIM_QUANTUMSIM: ( + "QuaLeSim_quantumsim", + "qualesim_quantumsim", + True, + Qisa.QCIS, + ), } def support(self, backend_type): diff --git a/src/quingo/backend/qualesim_quantumsim.py b/src/quingo/backend/qualesim_quantumsim.py index 7536f26..8e30107 100644 --- a/src/quingo/backend/qualesim_quantumsim.py +++ b/src/quingo/backend/qualesim_quantumsim.py @@ -1,67 +1,67 @@ -# from .backend_hub import BackendType -# from .if_backend import If_backend -# from quingo.core.exe_config import * -# from quingo.core.utils import * -# from dqcsim.plugin import * -# from dqcsim.host import * +from .backend_hub import BackendType +from .if_backend import If_backend +from quingo.core.exe_config import * +from quingo.core.utils import * +from dqcsim.plugin import * +from dqcsim.host import * -# logger = get_logger((__name__).split(".")[-1]) +logger = get_logger((__name__).split(".")[-1]) -# class QuaLeSim_quantumsim(If_backend): -# """A functional QCIS simulation backend using PyQCISim and Tequila.""" +class QuaLeSim_quantumsim(If_backend): + """A functional QCIS simulation backend using PyQCISim and Tequila.""" -# def __init__(self): -# super().__init__(BackendType.QUALESIM_QUANTUMSIM) -# self.sim = Simulator(stderr_verbosity=Loglevel.OFF) -# self.sim.with_backend("quantumsim", verbosity=Loglevel.OFF) -# self.res = None + def __init__(self): + super().__init__(BackendType.QUALESIM_QUANTUMSIM) + self.sim = Simulator(stderr_verbosity=Loglevel.OFF) + self.sim.with_backend("quantumsim", verbosity=Loglevel.OFF) + self.res = None -# def upload_program(self, prog_fn): -# prog_fn = ensure_path(prog_fn) -# if str(prog_fn).endswith(".qcis") or str(prog_fn).endswith(".qi"): -# self.sim.with_frontend(str(prog_fn), verbosity=Loglevel.OFF) -# else: -# raise TypeError( -# "The quantumsim simulator can only accept QCIS or QUIET-S instructions." -# ) + def upload_program(self, prog_fn): + prog_fn = ensure_path(prog_fn) + if str(prog_fn).endswith(".qcis") or str(prog_fn).endswith(".qi"): + self.sim.with_frontend(str(prog_fn), verbosity=Loglevel.OFF) + else: + raise TypeError( + "The quantumsim simulator can only accept QCIS or QUIET-S instructions." + ) -# def execute(self, exe_config: ExeConfig): -# if exe_config.mode == ExeMode.SimFinalResult: -# measure_mod = "one_shot" -# try: -# self.sim.simulate() -# res = self.sim.run( -# measure_mod=measure_mod, num_shots=exe_config.num_shots -# ) -# self.sim.stop() -# final_state = res["res"] -# final_state["quantum"] = tuple(final_state["quantum"]) -# return final_state["quantum"] -# except: -# raise ValueError( -# "Here is some wrong with ({}) for QUALESIM_QUANTUMSIM.".format( -# exe_config.mode -# ) -# ) + def execute(self, exe_config: ExeConfig): + if exe_config.mode == ExeMode.SimFinalResult: + measure_mod = "one_shot" + try: + self.sim.simulate() + res = self.sim.run( + measure_mod=measure_mod, num_shots=exe_config.num_shots + ) + self.sim.stop() + final_state = res["res"] + final_state["quantum"] = tuple(final_state["quantum"]) + return final_state["quantum"] + except: + raise ValueError( + "Here is some wrong with ({}) for QUALESIM_QUANTUMSIM.".format( + exe_config.mode + ) + ) -# if exe_config.mode == ExeMode.SimStateVector: -# measure_mod = "state_vector" -# try: -# self.sim.simulate() -# res = self.sim.run(measure_mod=measure_mod) -# self.sim.stop() -# final_state = eval(res["res"]) -# return final_state -# except: -# raise ValueError( -# "Here is some wrong with ({}) for QUALESIM_QUANTUMSIM.".format( -# exe_config.mode -# ) -# ) + if exe_config.mode == ExeMode.SimStateVector: + measure_mod = "state_vector" + try: + self.sim.simulate() + res = self.sim.run(measure_mod=measure_mod) + self.sim.stop() + final_state = eval(res["res"]) + return final_state + except: + raise ValueError( + "Here is some wrong with ({}) for QUALESIM_QUANTUMSIM.".format( + exe_config.mode + ) + ) -# raise ValueError( -# "Here is some wrong with ({}) for QUALESIM_QUANTUMSIM.".format( -# exe_config.mode -# ) -# ) + raise ValueError( + "Here is some wrong with ({}) for QUALESIM_QUANTUMSIM.".format( + exe_config.mode + ) + ) diff --git a/unittest/test_backends.py b/unittest/test_backends.py index a088519..25ae9ca 100644 --- a/unittest/test_backends.py +++ b/unittest/test_backends.py @@ -1,5 +1,6 @@ from quingo.backend.pyqcisim_tequila import PyQCISim_tequila from quingo.backend.pyqcisim_quantumsim import PyQCISim_quantumsim +from quingo.backend.qualesim_quantumsim import QuaLeSim_quantumsim from quingo.backend.symqc import IfSymQC from quingo.backend.backend_hub import BackendType, Backend_hub from quingo.backend.qisa import Qisa @@ -35,7 +36,7 @@ class Test_backends: # QuaLeSim_tequila and QuaLeSim_quantumsim default Qisa type is QCIS # single(QuaLeSim_tequila, BackendType.QUALESIM_TEQUILA, Qisa.QCIS, True) - # single(QuaLeSim_quantumsim, BackendType.QUALESIM_QUANTUMSIM, Qisa.QCIS, True) + single(QuaLeSim_quantumsim, BackendType.QUALESIM_QUANTUMSIM, Qisa.QCIS, True) single(PyQCISim_tequila, BackendType.TEQUILA, Qisa.QCIS, True) single(PyQCISim_quantumsim, BackendType.QUANTUM_SIM, Qisa.QCIS, True) single(IfSymQC, BackendType.SYMQC, Qisa.QCIS, True) @@ -50,8 +51,8 @@ class Test_backends: # single(QuaLeSim_tequila, qcis_fn) # single(QuaLeSim_tequila, quiet_fn) - # single(QuaLeSim_quantumsim, qcis_fn) - # single(QuaLeSim_quantumsim, quiet_fn) + single(QuaLeSim_quantumsim, qcis_fn) + single(QuaLeSim_quantumsim, quiet_fn) single(PyQCISim_tequila, qcis_fn) single(PyQCISim_quantumsim, qcis_fn) single(IfSymQC, qcis_fn) @@ -68,9 +69,9 @@ class Test_backends: # assert all(v in [[0, 0], [1, 1]] for v in res[1]) # single(QuaLeSim_tequila, qcis_fn) - # single(QuaLeSim_quantumsim, qcis_fn) + single(QuaLeSim_quantumsim, qcis_fn) # single(QuaLeSim_tequila, quiet_fn) - # single(QuaLeSim_quantumsim, quiet_fn) + single(QuaLeSim_quantumsim, quiet_fn) single(PyQCISim_tequila, qcis_fn) single(PyQCISim_quantumsim, qcis_fn) single(IfSymQC, qcis_fn) @@ -88,9 +89,9 @@ class Test_backends: assert all(v in [[0, 0], [1, 1]] for v in res[1]) # single(QuaLeSim_tequila, qcis_fn) - # single(QuaLeSim_quantumsim, qcis_fn) + single(QuaLeSim_quantumsim, qcis_fn) # single(QuaLeSim_tequila, quiet_fn) - # single(QuaLeSim_quantumsim, quiet_fn) + single(QuaLeSim_quantumsim, quiet_fn) single(PyQCISim_tequila, qcis_fn) single(PyQCISim_quantumsim, qcis_fn) single(IfSymQC, qcis_fn) @@ -107,9 +108,9 @@ class Test_backends: assert all(v in [[0, 0], [1, 1]] for v in res[1]) # single(BackendType.QUALESIM_TEQUILA, qcis_fn) - # single(BackendType.QUALESIM_QUANTUMSIM, qcis_fn) + single(BackendType.QUALESIM_QUANTUMSIM, qcis_fn) # single(BackendType.QUALESIM_TEQUILA, quiet_fn) - # single(BackendType.QUALESIM_QUANTUMSIM, quiet_fn) + single(BackendType.QUALESIM_QUANTUMSIM, quiet_fn) single(BackendType.TEQUILA, qcis_fn) single(BackendType.QUANTUM_SIM, qcis_fn) single(BackendType.SYMQC, qcis_fn) @@ -128,9 +129,9 @@ class Test_backends: assert dist(a, b) <= 0.01 # single(BackendType.QUALESIM_TEQUILA, quiet_fn2) - # single(BackendType.QUALESIM_QUANTUMSIM, quiet_fn2) + single(BackendType.QUALESIM_QUANTUMSIM, quiet_fn2) # single(BackendType.QUALESIM_TEQUILA, qcis_fn) - # single(BackendType.QUALESIM_QUANTUMSIM, qcis_fn) + single(BackendType.QUALESIM_QUANTUMSIM, qcis_fn) single(BackendType.QUANTUM_SIM, qcis_fn2) single(BackendType.SYMQC, qcis_fn2) @@ -163,7 +164,7 @@ class Test_backends: t2.start() # single(BackendType.QUALESIM_TEQUILA) - # single(BackendType.QUALESIM_QUANTUMSIM) + single(BackendType.QUALESIM_QUANTUMSIM) single(BackendType.QUANTUM_SIM) single(BackendType.TEQUILA) -- Gitee From 1c17c1b44b82e7e60216c2250a3db5db4c94e621 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E5=AE=9A=E4=B8=9C?= <3081545786@qq.com> Date: Fri, 29 Mar 2024 16:47:41 +0800 Subject: [PATCH 02/13] =?UTF-8?q?=F0=9F=A6=84=20refactor:=20rename=20dqcsi?= =?UTF-8?q?m=20to=20qualesim=20using=20qualesim=20version=201.0.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/quingo/backend/qualesim_quantumsim.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/quingo/backend/qualesim_quantumsim.py b/src/quingo/backend/qualesim_quantumsim.py index 8e30107..41af18d 100644 --- a/src/quingo/backend/qualesim_quantumsim.py +++ b/src/quingo/backend/qualesim_quantumsim.py @@ -2,8 +2,8 @@ from .backend_hub import BackendType from .if_backend import If_backend from quingo.core.exe_config import * from quingo.core.utils import * -from dqcsim.plugin import * -from dqcsim.host import * +from qualesim.plugin import * +from qualesim.host import * logger = get_logger((__name__).split(".")[-1]) -- Gitee From 306e31c6413ea63ed92d36c7eb7edafc6bca4ee8 Mon Sep 17 00:00:00 2001 From: Xiang Fu Date: Tue, 16 Apr 2024 16:50:49 +0800 Subject: [PATCH 03/13] =?UTF-8?q?=F0=9F=A6=84=20refactor(backends):=20unif?= =?UTF-8?q?y=20backend=20result=20format?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 统一运行时不同后端的返回接口 https://edu.gitee.com/hpcl_quanta/projects/458127/repos/quingo/quingo-runtime/issues/table?issue=I9GJI8 --- examples/bell_state/host.py | 4 +- examples/compile_info/host.py | 2 +- examples/ctrl_qubit/host.py | 2 +- examples/ghz/host.py | 2 +- examples/sim_backend/SimQuantumsim.py | 2 +- examples/sim_backend/SimSymQC.py | 2 +- examples/sim_backend/SimTequila.py | 2 +- examples/sim_exemode/SimFinalResult.py | 6 +- examples/sim_exemode/SimShots.py | 16 ++ examples/sim_exemode/SimStateVector.py | 6 +- setup.cfg | 1 - src/global_config.py | 3 - src/quingo/__init__.py | 4 +- src/quingo/backend/__init__.py | 6 + src/quingo/backend/backend_hub.py | 16 +- src/quingo/backend/pyqcisim_quantumsim.py | 22 +-- src/quingo/backend/pyqcisim_tequila.py | 18 +- src/quingo/backend/qualesim_quantumsim.py | 38 +++- .../backend/quingo_result_format_spec.md | 80 ++++++++ src/quingo/backend/readme.md | 40 ---- src/quingo/backend/symqc.py | 28 ++- src/quingo/core/exe_config.py | 23 ++- src/quingo/core/manager.py | 2 +- src/quingo/core/quingo_task.py | 2 +- src/quingo/lib/config-quingo.qfg | 69 ------- src/quingo/lib/standard_operations.qu | 25 --- src/quingo/utils.py | 23 +++ unittest/backends/test_backends.py | 66 +++++++ unittest/backends/test_qualesim.py | 35 ++++ unittest/backends/test_result_format.py | 139 ++++++++++++++ unittest/test_backends.py | 180 ------------------ unittest/test_compile_cmd.py | 34 ++-- unittest/test_execution.py | 46 ++--- unittest/test_preparation.py | 5 +- unittest/test_qcis/bell.qi | 6 +- .../{bell_copy.qcis => bell_no_msmt.qcis} | 0 .../{bell_copy.qi => bell_no_msmt.qi} | 0 unittest/test_quingo_task.py | 5 +- unittest/test_result.py | 76 -------- 39 files changed, 508 insertions(+), 528 deletions(-) create mode 100644 examples/sim_exemode/SimShots.py delete mode 100644 src/global_config.py create mode 100644 src/quingo/backend/quingo_result_format_spec.md delete mode 100644 src/quingo/backend/readme.md delete mode 100755 src/quingo/lib/config-quingo.qfg delete mode 100755 src/quingo/lib/standard_operations.qu create mode 100644 src/quingo/utils.py create mode 100644 unittest/backends/test_backends.py create mode 100644 unittest/backends/test_qualesim.py create mode 100644 unittest/backends/test_result_format.py delete mode 100644 unittest/test_backends.py rename unittest/test_qcis/{bell_copy.qcis => bell_no_msmt.qcis} (100%) rename unittest/test_qcis/{bell_copy.qi => bell_no_msmt.qi} (100%) delete mode 100644 unittest/test_result.py diff --git a/examples/bell_state/host.py b/examples/bell_state/host.py index a1a7d31..450a935 100644 --- a/examples/bell_state/host.py +++ b/examples/bell_state/host.py @@ -7,9 +7,9 @@ qu_file = Path(__file__).parent / "kernel.qu" def routine(circ_name, num_shots=1): task = Quingo_task(qu_file, circ_name) - cfg = ExeConfig(ExeMode.SimFinalResult, num_shots) + cfg = ExeConfig(ExeMode.SimFinalResult, num_shots=num_shots) qasm_fn = compile(task, params=(), config_file="") - res = execute(qasm_fn, BackendType.TEQUILA, cfg) # QuantumSim, SymQC + res = execute(qasm_fn, BackendType.QUALESIM_QUANTUMSIM, cfg) # QuantumSim, SymQC print("sim res: ", res) diff --git a/examples/compile_info/host.py b/examples/compile_info/host.py index 946c3b9..48a5de7 100644 --- a/examples/compile_info/host.py +++ b/examples/compile_info/host.py @@ -9,7 +9,7 @@ circ_name = "ghz" # configure the execution mode num_shots = 4 -cfg = ExeConfig(ExeMode.SimFinalResult, num_shots) +cfg = ExeConfig(ExeMode.SimShots, num_shots) # the input param num_qubits num_qubits = 5 diff --git a/examples/ctrl_qubit/host.py b/examples/ctrl_qubit/host.py index ae46361..ac9ce24 100644 --- a/examples/ctrl_qubit/host.py +++ b/examples/ctrl_qubit/host.py @@ -7,7 +7,7 @@ qu_file = Path(__file__).parent / "kernel.qu" def routine(circ_name, num_shots=1): task = Quingo_task(qu_file, circ_name) - cfg = ExeConfig(ExeMode.SimFinalResult, 10) + cfg = ExeConfig(ExeMode.SimShots, 10) # exemod 1 res = call(task, (), BackendType.QUANTUM_SIM, cfg) print("sim res: ", res) diff --git a/examples/ghz/host.py b/examples/ghz/host.py index 6b0b7b4..454ffc9 100644 --- a/examples/ghz/host.py +++ b/examples/ghz/host.py @@ -9,7 +9,7 @@ circ_name = "ghz" # configure the execution mode num_shots = 4 -cfg = ExeConfig(ExeMode.SimFinalResult, num_shots) +cfg = ExeConfig(ExeMode.SimShots, num_shots) # the input param num_qubits num_qubits = 5 diff --git a/examples/sim_backend/SimQuantumsim.py b/examples/sim_backend/SimQuantumsim.py index 4ec472b..eadd3fc 100644 --- a/examples/sim_backend/SimQuantumsim.py +++ b/examples/sim_backend/SimQuantumsim.py @@ -7,7 +7,7 @@ qu_file = Path(__file__).parent / "kernel.qu" def SimQuantumsim(circ_name, num_shots=1): task = Quingo_task(qu_file, circ_name) - cfg = ExeConfig(ExeMode.SimFinalResult, num_shots) + cfg = ExeConfig(ExeMode.SimShots, num_shots) qasm_fn = compile(task, params=(), config_file="") res = execute(qasm_fn, BackendType.QUANTUM_SIM, cfg) print("sim res: ", res) diff --git a/examples/sim_backend/SimSymQC.py b/examples/sim_backend/SimSymQC.py index 9ca023e..d5fcb32 100644 --- a/examples/sim_backend/SimSymQC.py +++ b/examples/sim_backend/SimSymQC.py @@ -7,7 +7,7 @@ qu_file = Path(__file__).parent / "kernel.qu" def SimSymQC(circ_name, num_shots=1): task = Quingo_task(qu_file, circ_name) - cfg = ExeConfig(ExeMode.SimFinalResult, num_shots) + cfg = ExeConfig(ExeMode.SimShots, num_shots) qasm_fn = compile(task, params=(), config_file="") res = execute(qasm_fn, BackendType.SYMQC, cfg) print("sim res: ", res) diff --git a/examples/sim_backend/SimTequila.py b/examples/sim_backend/SimTequila.py index 5a3dd07..b8861d2 100644 --- a/examples/sim_backend/SimTequila.py +++ b/examples/sim_backend/SimTequila.py @@ -7,7 +7,7 @@ qu_file = Path(__file__).parent / "kernel.qu" def SimTequila(circ_name, num_shots=1): task = Quingo_task(qu_file, circ_name) - cfg = ExeConfig(ExeMode.SimFinalResult, num_shots) + cfg = ExeConfig(ExeMode.SimShots, num_shots) qasm_fn = compile(task, params=(), config_file="") res = execute(qasm_fn, BackendType.TEQUILA, cfg) # QuantumSim, SymQC print("sim res: ", res) diff --git a/examples/sim_exemode/SimFinalResult.py b/examples/sim_exemode/SimFinalResult.py index 60850b6..c3063b5 100644 --- a/examples/sim_exemode/SimFinalResult.py +++ b/examples/sim_exemode/SimFinalResult.py @@ -5,12 +5,12 @@ from pathlib import Path qu_file = Path(__file__).parent / "kernel.qu" -def SimFinalResult(circ_name, num_shots=1): +def SimFinalResult(circ_name): task = Quingo_task(qu_file, circ_name) - cfg = ExeConfig(ExeMode.SimFinalResult, num_shots) + cfg = ExeConfig(ExeMode.SimFinalResult) qasm_fn = compile(task, params=(), config_file="") res = execute(qasm_fn, BackendType.QUANTUM_SIM, cfg) # QuantumSim, SymQC print("sim res: ", res) -SimFinalResult("bell_state", 10) +SimFinalResult("bell_state") diff --git a/examples/sim_exemode/SimShots.py b/examples/sim_exemode/SimShots.py new file mode 100644 index 0000000..777f221 --- /dev/null +++ b/examples/sim_exemode/SimShots.py @@ -0,0 +1,16 @@ +from quingo import * +from pathlib import Path + + +qu_file = Path(__file__).parent / "kernel.qu" + + +def SimShots(circ_name, num_shots=1): + task = Quingo_task(qu_file, circ_name) + cfg = ExeConfig(ExeMode.SimShots, num_shots) + qasm_fn = compile(task, params=(), config_file="") + res = execute(qasm_fn, BackendType.QUANTUM_SIM, cfg) # QuantumSim, SymQC + print("sim res: ", res) + + +SimShots("bell_state", 10) diff --git a/examples/sim_exemode/SimStateVector.py b/examples/sim_exemode/SimStateVector.py index 35b6182..9bc525d 100644 --- a/examples/sim_exemode/SimStateVector.py +++ b/examples/sim_exemode/SimStateVector.py @@ -9,10 +9,8 @@ def SimStateVector(circ_name): task = Quingo_task(qu_file, circ_name) cfg = ExeConfig(ExeMode.SimStateVector) qasm_fn = compile(task, params=(), config_file="") - res = execute(qasm_fn, BackendType.SYMQC, cfg) - print("sim res for bell state is:") - print("classical:", res["classical"]) - print("quantum:", res["quantum"]) + res = execute(qasm_fn, BackendType.QUANTUM_SIM, cfg) + print(res) SimStateVector("bell_state") diff --git a/setup.cfg b/setup.cfg index f2849ce..004ff59 100644 --- a/setup.cfg +++ b/setup.cfg @@ -29,7 +29,6 @@ install_requires = termcolor requests tqdm - pyezq qualesim qualesim-quiets qualesim-quantumsim diff --git a/src/global_config.py b/src/global_config.py deleted file mode 100644 index 1060610..0000000 --- a/src/global_config.py +++ /dev/null @@ -1,3 +0,0 @@ -from pathlib import Path - -SRC_PATH = cur_dir = Path(__file__).parent.parent diff --git a/src/quingo/__init__.py b/src/quingo/__init__.py index ff685c5..236e124 100755 --- a/src/quingo/__init__.py +++ b/src/quingo/__init__.py @@ -2,5 +2,5 @@ from quingo.core.exe_config import ExeConfig, ExeMode from quingo.core.compile import compile from quingo.core.manager import execute, call from quingo.core.quingo_task import Quingo_task -from quingo.backend.backend_hub import * -from quingo.backend.qisa import * +from quingo.backend.backend_hub import BackendType +from quingo.backend.qisa import Qisa diff --git a/src/quingo/backend/__init__.py b/src/quingo/backend/__init__.py index e69de29..44654bc 100755 --- a/src/quingo/backend/__init__.py +++ b/src/quingo/backend/__init__.py @@ -0,0 +1,6 @@ +from quingo.backend.backend_hub import BackendType +from quingo.backend.pyqcisim_tequila import PyQCISim_tequila +from quingo.backend.pyqcisim_quantumsim import PyQCISim_quantumsim +from quingo.backend.qualesim_quantumsim import QuaLeSim_quantumsim +from quingo.backend.symqc import IfSymQC +from quingo.backend.qisa import Qisa diff --git a/src/quingo/backend/backend_hub.py b/src/quingo/backend/backend_hub.py index 234cb77..64b45c3 100755 --- a/src/quingo/backend/backend_hub.py +++ b/src/quingo/backend/backend_hub.py @@ -1,6 +1,7 @@ import importlib import enum -from .qisa import Qisa +from quingo.backend.qisa import Qisa +from quingo.utils import singleton class BackendType(enum.Enum): @@ -9,19 +10,8 @@ class BackendType(enum.Enum): SYMQC = enum.auto() QUANTIFY = enum.auto() XIAOHONG = enum.auto() - # QUALESIM_TEQUILA = enum.auto() QUALESIM_QUANTUMSIM = enum.auto() - - -def singleton(cls): - _instance = {} - - def inner(): - if cls not in _instance: - _instance[cls] = cls() - return _instance[cls] - - return inner + # QUALESIM_TEQUILA = enum.auto() @singleton diff --git a/src/quingo/backend/pyqcisim_quantumsim.py b/src/quingo/backend/pyqcisim_quantumsim.py index 1a6bae1..4628c94 100755 --- a/src/quingo/backend/pyqcisim_quantumsim.py +++ b/src/quingo/backend/pyqcisim_quantumsim.py @@ -28,21 +28,21 @@ class PyQCISim_quantumsim(If_backend): """Execute the given quantum circuit. Args: - mode (str): the simulation mode to use: - - "one_shot": the simulation result is a dictionary with each key being a qubit - measured, and the value is the outcome of measuring this qubit. - - "final_state": the simulation result is a two-level dictionary: - { - 'classical': {'Q1': 1, 'Q2': 0}, - 'quantum': (['Q3', 'Q4'], array([0, 1, 0, 0])) - } - - num_shots (int): the number of iterations performed in `one_shot` mode. + + The number of shots is specified in exe_config.num_shots, which is only valid for + ExeMode.SimShots. """ - if exe_config.mode == ExeMode.SimStateVector: - raw_res = self.sim.simulate("final_state") + if exe_config.mode == ExeMode.SimShots: + raw_res = self.sim.simulate("one_shot", exe_config.num_shots) return raw_res if exe_config.mode == ExeMode.SimFinalResult: - return self.sim.simulate("one_shot", exe_config.num_shots) + raw_res = self.sim.simulate("final_result") + return raw_res + + if exe_config.mode == ExeMode.SimStateVector: + raw_res = self.sim.simulate("state_vector") + return raw_res["quantum"] raise ValueError( "Unsupported execution mode ({}) for quantumsim.".format(exe_config.mode) diff --git a/src/quingo/backend/pyqcisim_tequila.py b/src/quingo/backend/pyqcisim_tequila.py index e3ed043..c87add2 100644 --- a/src/quingo/backend/pyqcisim_tequila.py +++ b/src/quingo/backend/pyqcisim_tequila.py @@ -23,9 +23,25 @@ class PyQCISim_tequila(If_backend): self.sim.compile(program) def execute(self, exe_config: ExeConfig): - if exe_config.mode == ExeMode.SimFinalResult: + """Execute the given quantum circuit. + Args: + - exe_config (ExeConfig): the configuration used to perform simulation by SymQC. + + The number of shots is specified in exe_config.num_shots, which is only valid for + ExeMode.SimShots. + """ + + if exe_config.mode == ExeMode.SimShots: return self.sim.simulate("one_shot", exe_config.num_shots) + if exe_config.mode == ExeMode.SimFinalResult: + return self.sim.simulate("final_result") + + if exe_config.mode == ExeMode.SimStateVector: + raw_res = self.sim.simulate("state_vector") + print("result from pyqcisim_tequila: ", raw_res) + return raw_res + raise ValueError( "Unsupported execution mode ({}) for TEQUILA.".format(exe_config.mode) ) diff --git a/src/quingo/backend/qualesim_quantumsim.py b/src/quingo/backend/qualesim_quantumsim.py index 41af18d..e89b1fb 100644 --- a/src/quingo/backend/qualesim_quantumsim.py +++ b/src/quingo/backend/qualesim_quantumsim.py @@ -27,6 +27,28 @@ class QuaLeSim_quantumsim(If_backend): ) def execute(self, exe_config: ExeConfig): + if exe_config.mode == ExeMode.SimShots: + measure_mod = "one_shot" + try: + self.sim.simulate() + res = self.sim.run( + measure_mod=measure_mod, num_shots=exe_config.num_shots + ) + self.sim.stop() + + final_state = res["res"] + final_state["quantum"] = tuple(final_state["quantum"]) + result = final_state["quantum"] + + return result + + except Exception as e: + raise ValueError( + "error in QuaLeSim_QuantumSim simulation with mode ({}): {}".format( + exe_config.mode, e + ) + ) + if exe_config.mode == ExeMode.SimFinalResult: measure_mod = "one_shot" try: @@ -38,10 +60,11 @@ class QuaLeSim_quantumsim(If_backend): final_state = res["res"] final_state["quantum"] = tuple(final_state["quantum"]) return final_state["quantum"] - except: + + except Exception as e: raise ValueError( - "Here is some wrong with ({}) for QUALESIM_QUANTUMSIM.".format( - exe_config.mode + "error in QuaLeSim_QuantumSim simulation with mode ({}): {}".format( + exe_config.mode, e ) ) @@ -53,15 +76,16 @@ class QuaLeSim_quantumsim(If_backend): self.sim.stop() final_state = eval(res["res"]) return final_state - except: + + except Exception as e: raise ValueError( - "Here is some wrong with ({}) for QUALESIM_QUANTUMSIM.".format( - exe_config.mode + "error in QuaLeSim_QuantumSim simulation with mode ({}): {}".format( + exe_config.mode, e ) ) raise ValueError( - "Here is some wrong with ({}) for QUALESIM_QUANTUMSIM.".format( + "Unsupported execution mode ({}) for QuaLeSim_QuantumSim.".format( exe_config.mode ) ) diff --git a/src/quingo/backend/quingo_result_format_spec.md b/src/quingo/backend/quingo_result_format_spec.md new file mode 100644 index 0000000..1df8994 --- /dev/null +++ b/src/quingo/backend/quingo_result_format_spec.md @@ -0,0 +1,80 @@ +# Quingo Backend Result Format +Currently, Quingo supports four kinds of result format: +- SimShots (shot) +- SimFinalResult (final result) +- SimStateVector (state vector) +- SymbolicStateVector (symbolic state vector) + +The real machine can only return the result in the shot mode. + +## SimShot +In this mode, only classical information will be recorded, and the quantum state will be dropped. An extra parameter `num_shots` is accepted for this mode, which tells how many times this experiment will be repeated for. + +The output is a 2-element tuple: + - a list of qubit names or classical variables (`names`) + - a 2-d list, with i-th value in the j-th inner list corresponding to the i-th qubit or classical variable in `names` in the j-th run. + +An Example result of a simulation with num_shots=3: +```python +(['Q3', 'Q4', 'Q5', 'Q6', 'Q7'], + [[1, 1, 0, 0, 0], + [1, 1, 0, 0, 0], + [1, 1, 0, 0, 0]]) +``` + +## SimStateVector +In this mode, measurements are only allowed at the end of the entire program, and no mid-circuit measurement is allowed. All measurements in the end will be dropped while performing the simulation. + +result is a tuple that contains two elements: +- The first element is a list of qubits, and +- the second element is a complex array representing the state of the quantum system (which is a 1-d list). + +Example: +For the following QUIET-s program: +```quiet +func main()->(int c1, int c2): + qubit q1 + qubit q2 + H q1 + CNOT q1, q2 +end +``` + +The result shall be: +```python +{ + 'classical': {}, + 'quantum': (['q1', 'q2'], + [(0.7071067811865474+0j), 0j, 0j, (0.7071067811865476+0j)]) +} +``` + +## SymbolicStateVector +Everything is the same as `SimStateVector`, except that the state is represented using symbols in sympy. + +## SimFinalResult +In this mode, both classical result and quantum result will be returned in a dictionary. The `num_shots` parameter is not allowed in this mode. + +- The `classical` result is a dictionary that maps classical variables to their values. Each key-value pair represents a classical variable and its corresponding value. + +- The `quantum` result is a tuple that contains two elements. The first element is a list of qubits, and the second element is a complex array representing the state of the quantum system. The qubits are represented as strings in the list. The complex array represents the amplitudes of the quantum states, where each element corresponds to a specific quantum state. + +For example: +```quiet +func main()->(int c1, int c2): + qubit q1 + qubit q2 + H q1 + CNOT q1, q2 + measure(q1)->c1 +end +``` + +Two runs of this program returns different results: +```python + {'classical': {'q1': 1}, 'quantum': (['q2'], [0j, (1+0j)])} +``` + +```python +{'classical': {'q1': 0}, 'quantum': (['q2'], [(1+0j), 0j])} +``` diff --git a/src/quingo/backend/readme.md b/src/quingo/backend/readme.md deleted file mode 100644 index 2f06f04..0000000 --- a/src/quingo/backend/readme.md +++ /dev/null @@ -1,40 +0,0 @@ -## the result -1. 对于state_vector模式 - - 结果如下: - ``` - 模拟: - .file: - .gate: - .body: - func main()->(int c1, int c2): - qubit q1 - qubit q2 - H q1 - CNOT q1, q2 - end - res = {'classical': {}, 'quantum': (['q1', 'q2'], [(0.7071067811865474+0j), 0j, 0j, (0.7071067811865476+0j)])} - - 模拟: - .file: - .gate: - .body: - func main()->(int c1, int c2): - qubit q1 - qubit q2 - H q1 - CNOT q1, q2 - measure(q1)->c1 - end - res = {'classical': {'q1': 1}, 'quantum': (['q2'], [0j, (1+0j)])} - // - res = {'classical': {'q1': 0}, 'quantum': (['q2'], [(1+0j), 0j])} - ``` - - 对于未测量的量子比特,返回量子比特序列及其对应的状态向量 - - 对于已测量的量子比特,将其及对应的测量值存入classical中,quantum中存储未测量的量子比特的状态向量。(暂时未考虑重复利用已测量的量子比特的情况……) - -2. RealMachine模式 - ```python - res = {'qubit':[0,6], 'result':[[0,1], [1,0], [1,0], [0,1]]} - ``` - - `'qubits'`字段:所有qubit的物理编号 - - `'results'`字段:按`'qubits'`字段中的顺序,每次实验测量的结果 \ No newline at end of file diff --git a/src/quingo/backend/symqc.py b/src/quingo/backend/symqc.py index 88923d1..914e47c 100644 --- a/src/quingo/backend/symqc.py +++ b/src/quingo/backend/symqc.py @@ -31,27 +31,21 @@ class IfSymQC(If_backend): def execute(self, exe_config: ExeConfig): """Execute the given quantum circuit. Args: - - mode (str): the simulation mode to use: - - "one_shot": the simulation result is a dictionary with each key being a qubit - measured, and the value is the outcome of measuring this qubit. - - "final_state": the simulation result is a two-level dictionary: - { - 'classical': {'Q1': 1, 'Q2': 0}, - 'quantum': (['Q3', 'Q4'], array([0, 1, 0, 0])) - } - - num_shots (int): the number of iterations performed in `one_shot` mode. + - exe_config (ExeConfig): the configuration used to perform simulation by SymQC. + + The number of shots is specified in exe_config.num_shots, which is only valid for + ExeMode.SimShots. """ - if exe_config.mode == ExeMode.SimStateVector: - raw_res = self.sim.simulate("final_state") - return raw_res + if exe_config.mode == ExeMode.SimShots: + return self.sim.simulate("one_shot", exe_config.num_shots) if exe_config.mode == ExeMode.SimFinalResult: - return self.sim.simulate("one_shot", exe_config.num_shots) + raw_res = self.sim.simulate("final_state") + return raw_res - if exe_config.mode == ExeMode.SimMatrix: - raise NotImplementedError( - "Runtime has not supported SimMatrix with SymQC yet." - ) + if exe_config.mode == ExeMode.SimStateVector: + raw_res = self.sim.simulate("final_state") + return raw_res["quantum"] raise ValueError( "Unsupported execution mode ({}) for symqc.".format(exe_config.mode) diff --git a/src/quingo/core/exe_config.py b/src/quingo/core/exe_config.py index db9804e..0c84518 100644 --- a/src/quingo/core/exe_config.py +++ b/src/quingo/core/exe_config.py @@ -2,24 +2,27 @@ import enum class ExeMode(enum.Enum): + """ + Enumeration representing different result format. + + Attributes: + SimFinalResult: for obtaining the final result. + SimStateVector: Simulation mode for obtaining the state vector. + SimMatrix: Simulation mode for obtaining the matrix representation. + RealMachine: Mode for executing on a real quantum machine. + """ + + SimShots = enum.auto() SimFinalResult = enum.auto() SimStateVector = enum.auto() - SimMatrix = enum.auto() + SymbolicStateVector = enum.auto() RealMachine = enum.auto() -def is_simulation(exe_mode): - return exe_mode in [ - ExeMode.SimFinalResult, - ExeMode.SimStateVector, - ExeMode.SimMatrix, - ] - - class ExeConfig: def __init__( self, - mode: ExeMode = ExeMode.SimFinalResult, + mode: ExeMode = ExeMode.SimShots, num_shots: int = 1, xh_login_key: str = None, # use for connecting XIAOHONG xh_machine_name: str = None, # use for connecting XIAOHONG diff --git a/src/quingo/core/manager.py b/src/quingo/core/manager.py index 76e5642..88fc009 100755 --- a/src/quingo/core/manager.py +++ b/src/quingo/core/manager.py @@ -12,7 +12,7 @@ logger = get_logger((__name__).split(".")[-1]) def verify_backend_config(backend: BackendType, exe_config: ExeConfig) -> bool: """Check if the combination of backend and execution configuration is valid.""" - if backend == BackendType.XIAOHONG and is_simulation(exe_config.mode): + if (backend == BackendType.XIAOHONG) and (exe_config.mode != ExeMode.RealMachine): return False if backend == BackendType.QUANTIFY: diff --git a/src/quingo/core/quingo_task.py b/src/quingo/core/quingo_task.py index 1d4b587..9f0104e 100644 --- a/src/quingo/core/quingo_task.py +++ b/src/quingo/core/quingo_task.py @@ -107,7 +107,7 @@ class Quingo_task: BackendType.TEQUILA, BackendType.SYMQC, BackendType.XIAOHONG, - # BackendType.QUALESIM_QUANTUMSIM, + BackendType.QUALESIM_QUANTUMSIM, # BackendType.QUALESIM_TEQUILA, ]: return Qisa.QCIS diff --git a/src/quingo/lib/config-quingo.qfg b/src/quingo/lib/config-quingo.qfg deleted file mode 100755 index c34a2b8..0000000 --- a/src/quingo/lib/config-quingo.qfg +++ /dev/null @@ -1,69 +0,0 @@ -package config.json - - -{ - "Rx90": { - "duration": 20, - "matrix": [ [0.0,0.0], [1.0,0.0], [1.0,0.0], [0.0,0.0] ], - "type": "single-qubit", - "eqasm": "rx90" - }, - "X": { - "duration": 20, - "matrix": [ [0.0,0.0], [1.0,0.0], [1.0,0.0], [0.0,0.0] ], - "type": "single-qubit", - "eqasm": "rx180" - }, - "Y": { - "duration": 20, - "matrix": [ [0.0,0.0], [0.0,-1.0], [0.0,1.0], [0.0,0.0] ], - "type": "single-qubit", - "eqasm": "ry180" - }, - "Z": { - "duration": 20, - "matrix": [ [1.0,0.0], [0.0,0.0], [0.0,0.0], [-1.0,0.0] ], - "type": "single-qubit", - "eqasm": "rz180" - }, - "T": { - "duration": 20, - "matrix": [ [1.0,0.0], [0.0,0.0], [0.0,0.0], [-1.0,0.0] ], - "type": "single-qubit", - "eqasm": "t" - }, - "Tdag": { - "duration": 20, - "matrix": [ [1.0,0.0], [0.0,0.0], [0.0,0.0], [-1.0,0.0] ], - "type": "single-qubit", - "eqasm": "tdag" - }, - "S": { - "duration": 20, - "matrix": [ [1.0,0.0], [0.0,0.0], [0.0,0.0], [-1.0,0.0] ], - "type": "single-qubit", - "eqasm": "S" - }, - "H": { - "duration": 40, - "matrix": [[1.0,0.0], [1.0,0.0], [1.0,0.0], [-1.0,0.0]] , - "type": "single-qubit", - "eqasm": "H" - }, - "CZ": { - "duration": 40, - "matrix": [ - [1.0,0.0], [0.0,0.0], [0.0,0.0], [0.0,0.0], - [0.0,0.0], [1.0,0.0], [0.0,0.0], [0.0,0.0], - [0.0,0.0], [0.0,0.0], [1.0,0.0], [0.0,0.0], - [0.0,0.0], [0.0,0.0], [0.0,0.0], [-1.0,0.0] - ], - "type": "two-qubit", - "eqasm": "CZ" - }, - "measure": { - "duration": 600, - "type":"meas", - "eqasm":"MeasZ" - } -} diff --git a/src/quingo/lib/standard_operations.qu b/src/quingo/lib/standard_operations.qu deleted file mode 100755 index 85abfb0..0000000 --- a/src/quingo/lib/standard_operations.qu +++ /dev/null @@ -1,25 +0,0 @@ -opaque Rx90(q:qubit): unit; -opaque X(q:qubit): unit; -opaque Y(q:qubit): unit; -opaque Z(q:qubit): unit; -opaque T(q:qubit): unit; -opaque Tdag(q:qubit): unit; -opaque S(q:qubit): unit; -opaque H(q:qubit): unit; -opaque CZ(c:qubit, t:qubit): unit; -opaque measure(c:qubit): bool; - -operation init(q: qubit) : unit { - bool a; - a = measure(q); - if (a) { - X(q); - } -} - -operation CNOT(c: qubit, t: qubit): unit -{ - H(t); - CZ(c, t); - H(t); -} diff --git a/src/quingo/utils.py b/src/quingo/utils.py new file mode 100644 index 0000000..1e20c67 --- /dev/null +++ b/src/quingo/utils.py @@ -0,0 +1,23 @@ +import sympy as sp + + +def singleton(cls): + _instance = {} + + def inner(): + if cls not in _instance: + _instance[cls] = cls() + return _instance[cls] + + return inner + + +def number_distance(a, b): + """calculates the distance between two complex numbers or two sympy numbers.""" + if isinstance(a, complex) and isinstance(b, complex): + return (a.real - b.real) ** 2 + (a.imag - b.imag) ** 2 + + if hasattr(a, "evalf") and hasattr(b, "evalf"): + return (a.evalf() - b.evalf()) ** 2 + + raise ValueError("unsupported types for dist: {} and {}".format(type(a), type(b))) diff --git a/unittest/backends/test_backends.py b/unittest/backends/test_backends.py new file mode 100644 index 0000000..1bf86e2 --- /dev/null +++ b/unittest/backends/test_backends.py @@ -0,0 +1,66 @@ +from quingo.backend.pyqcisim_tequila import PyQCISim_tequila +from quingo.backend.pyqcisim_quantumsim import PyQCISim_quantumsim +from quingo.backend.qualesim_quantumsim import QuaLeSim_quantumsim +from quingo.backend.symqc import IfSymQC +from quingo.backend.backend_hub import BackendType, Backend_hub +from quingo.backend.qisa import Qisa +from quingo.core.exe_config import * +import threading +from quingo.utils import number_distance +from pathlib import Path + + +unittest_dir = Path(__file__).parent / ".." +qcis_fn = unittest_dir / "test_qcis" / "bell.qcis" +qcis_fn2 = unittest_dir / "test_qcis" / "bell_no_msmt.qcis" +quiet_fn = unittest_dir / "test_qcis" / "bell.qi" +quiet_fn2 = unittest_dir / "test_qcis" / "bell_no_msmt.qi" + + +# progress: 2023-10-09 +# finished test on quantumsim and Tequila. +class Test_backends: + def test_basic(self): + def single(BackendClass, type, qisa, is_sim): + sim = BackendClass() + assert sim.get_type() == type + assert sim.get_qisa() == qisa + assert sim.is_simulator() == is_sim + + # QuaLeSim_tequila and QuaLeSim_quantumsim default Qisa type is QCIS + # single(QuaLeSim_tequila, BackendType.QUALESIM_TEQUILA, Qisa.QCIS, True) + single(QuaLeSim_quantumsim, BackendType.QUALESIM_QUANTUMSIM, Qisa.QCIS, True) + single(PyQCISim_tequila, BackendType.TEQUILA, Qisa.QCIS, True) + single(PyQCISim_quantumsim, BackendType.QUANTUM_SIM, Qisa.QCIS, True) + single(IfSymQC, BackendType.SYMQC, Qisa.QCIS, True) + + def test_upload_program(self): + def single(BackendClass, qasm_fn): + sim = BackendClass() + try: + sim.upload_program(qasm_fn) + except Exception as e: + assert False, "upload_program failed: {}".format(e) + + # single(QuaLeSim_tequila, qcis_fn) + # single(QuaLeSim_tequila, quiet_fn) + single(QuaLeSim_quantumsim, qcis_fn) + single(QuaLeSim_quantumsim, quiet_fn) + single(PyQCISim_tequila, qcis_fn) + single(PyQCISim_quantumsim, qcis_fn) + single(IfSymQC, qcis_fn) + + def test_get_from_hub(self): + def single(backend_type, simulator_class): + hub = Backend_hub() + sim = hub.get_instance(backend_type) + assert isinstance(sim, simulator_class) + + single(BackendType.QUANTUM_SIM, PyQCISim_quantumsim) + single(BackendType.TEQUILA, PyQCISim_tequila) + single(BackendType.QUALESIM_QUANTUMSIM, QuaLeSim_quantumsim) + single(BackendType.SYMQC, IfSymQC) + + +if __name__ == "__main__": + pass diff --git a/unittest/backends/test_qualesim.py b/unittest/backends/test_qualesim.py new file mode 100644 index 0000000..30f90b5 --- /dev/null +++ b/unittest/backends/test_qualesim.py @@ -0,0 +1,35 @@ +from quingo.backend import QuaLeSim_quantumsim +from quingo.core.exe_config import ExeConfig, ExeMode +from quingo import execute +from quingo.utils import number_distance +from pathlib import Path + + +unittest_dir = Path(__file__).parent / ".." +bell_qcis_fn = unittest_dir / "test_qcis" / "bell.qcis" +bell_no_msmt_qcis_fn = unittest_dir / "test_qcis" / "bell_no_msmt.qcis" + +bell_quiet_fn = unittest_dir / "test_qcis" / "bell.qi" +bell_no_msmt_quiet_fn = unittest_dir / "test_qcis" / "bell_no_msmt.qi" + + +class TestQuaLeSimQuantumSim: + def test_qcis(self): + simulator = QuaLeSim_quantumsim() + simulator.upload_program(bell_qcis_fn) + num_shots = 10 + exe_config = ExeConfig(ExeMode.SimShots, num_shots) + names, result = simulator.execute(exe_config) + assert names == ["Q1", "Q2"] + assert len(result) == num_shots + assert all(i == j for i, j in result) + + def test_quiet(self): + simulator = QuaLeSim_quantumsim() + simulator.upload_program(bell_quiet_fn) + num_shots = 10 + exe_config = ExeConfig(ExeMode.SimShots, num_shots) + names, result = simulator.execute(exe_config) + assert names == ["Q1", "Q2"] + assert len(result) == num_shots + assert all(i == j for i, j in result) diff --git a/unittest/backends/test_result_format.py b/unittest/backends/test_result_format.py new file mode 100644 index 0000000..d946aa7 --- /dev/null +++ b/unittest/backends/test_result_format.py @@ -0,0 +1,139 @@ +from quingo.backend.backend_hub import BackendType, Backend_hub +from quingo.core.exe_config import ExeConfig, ExeMode +from quingo import execute +from quingo.utils import number_distance +from pathlib import Path +import pytest + +cur_dir = Path(__file__).parent + +bell_qcis_fn = cur_dir / ".." / "test_qcis" / "bell.qcis" +bell_no_msmt_qcis_fn = cur_dir / ".." / "test_qcis" / "bell_no_msmt.qcis" + + +quiet_fn = cur_dir / ".." / "test_qcis" / "bell.qi" +quiet_fn2 = cur_dir / ".." / "test_qcis" / "bell_no_msmt.qi" + + +backends = [ + BackendType.QUANTUM_SIM, + BackendType.TEQUILA, + BackendType.QUALESIM_QUANTUMSIM, + BackendType.SYMQC, +] +num_shots = [5, 10] + + +@pytest.fixture(params=backends) +def get_simulator(request): + return request.param + + +@pytest.fixture(params=num_shots) +def get_num_shots(request): + return request.param + + +def test_shot_with_msmt(get_simulator, get_num_shots): + simulator = get_simulator + num_shots = get_num_shots + + exe_config = ExeConfig(ExeMode.SimShots, num_shots) + names, result = execute(bell_qcis_fn, simulator, exe_config) + print("result for {}: ".format(simulator), names, result) + assert names == ["Q1", "Q2"] + assert len(result) == num_shots + assert all(i == j for i, j in result) + + +def test_shot_without_msmt(get_simulator, get_num_shots): + simulator = get_simulator + num_shots = get_num_shots + + exe_config = ExeConfig(ExeMode.SimShots, num_shots) + names, result = execute(bell_no_msmt_qcis_fn, simulator, exe_config) + assert names == [] + assert len(result) == num_shots + assert all(len(l) == 0 for l in result) + + +def test_final_result_with_msmt(get_simulator, get_num_shots): + simulator = get_simulator + num_shots = get_num_shots + + exe_config = ExeConfig(ExeMode.SimFinalResult, num_shots=num_shots) + result = execute(bell_qcis_fn, simulator, exe_config) + print("result: ", result) + + +def test_final_result_without_msmt(get_simulator, get_num_shots): + simulator = get_simulator + num_shots = get_num_shots + + exe_config = ExeConfig(ExeMode.SimFinalResult, num_shots=num_shots) + result = execute(bell_no_msmt_qcis_fn, simulator, exe_config) + print("result: ", result) + + +class TestStateVector: + """When simulating a quantum program in the state vector mode, + the result should be a tuple: + ( + ["Q1", "Q2"], + [0.7071067811865475, 0.0, 0.0, 0.7071067811865475] + ) + """ + + def vec_tests(self): + def vec_test_without_msmt(simulator): + exe_config = ExeConfig(ExeMode.SimStateVector) + state_vec_res = execute(bell_no_msmt_qcis_fn, simulator, exe_config) + assert len(state_vec_res) == 2 + assert state_vec_res[0] == ["Q1", "Q2"] + + assert len(state_vec_res[1]) == 4 + + vec_test_without_msmt(BackendType.TEQUILA) + vec_test_without_msmt(BackendType.QUANTUM_SIM) + vec_test_without_msmt(BackendType.SYMQC) + vec_test_without_msmt(BackendType.QUALESIM_QUANTUMSIM) + + def vec_tests_with_msmt(self): + + def vec_test_with_msmt(simulator): + exe_config = ExeConfig(ExeMode.SimStateVector) + state_vec_res = execute(bell_qcis_fn, simulator, exe_config) + assert len(state_vec_res) == 2 + assert state_vec_res[0] == ["Q1", "Q2"] + + assert len(state_vec_res[1]) == 4 + + vec_test_with_msmt(BackendType.TEQUILA) + vec_test_with_msmt(BackendType.QUANTUM_SIM) + vec_test_with_msmt(BackendType.SYMQC) + vec_test_with_msmt(BackendType.QUALESIM_QUANTUMSIM) + + def test_quantumsim_with_msmt(self): + exe_config = ExeConfig(ExeMode.SimStateVector) + state_vec_res = execute( + bell_no_msmt_qcis_fn, BackendType.QUANTUM_SIM, exe_config + ) + assert len(state_vec_res) == 2 + assert state_vec_res[0] == ["Q1", "Q2"] + + assert len(state_vec_res[1]) == 4 + + +if __name__ == "__main__": + # test_final_result_with_msmt() + test_shot_without_msmt(BackendType.QUANTUM_SIM, 10) + # test = TestFinalResult() + # # test.test_sim_with_msmt() + # # test.test_sim_without_msmt() + + # # test = TestStateVector() + # # test.test_symqc_with_msmt() + # # test.test_symqc_without_msmt() + # # test.test_quantumsim_with_msmt() + # test = TestShots() + # test.test_shots() diff --git a/unittest/test_backends.py b/unittest/test_backends.py deleted file mode 100644 index 25ae9ca..0000000 --- a/unittest/test_backends.py +++ /dev/null @@ -1,180 +0,0 @@ -from quingo.backend.pyqcisim_tequila import PyQCISim_tequila -from quingo.backend.pyqcisim_quantumsim import PyQCISim_quantumsim -from quingo.backend.qualesim_quantumsim import QuaLeSim_quantumsim -from quingo.backend.symqc import IfSymQC -from quingo.backend.backend_hub import BackendType, Backend_hub -from quingo.backend.qisa import Qisa -from quingo.core.exe_config import * -from pathlib import Path -import threading -import random -from global_config import SRC_PATH - -cur_dir = SRC_PATH / "unittest" / "" -qcis_fn = cur_dir / "test_qcis" / "bell.qcis" -qcis_fn2 = cur_dir / "test_qcis" / "bell_copy.qcis" -quiet_fn = cur_dir / "test_qcis" / "bell.qi" -quiet_fn2 = cur_dir / "test_qcis" / "bell_copy.qi" - - -def dist(a, b): - if isinstance(a, complex) and isinstance(b, complex): - return (a.real - b.real) ** 2 + (a.imag - b.imag) ** 2 - else: - return (a.evalf() - b.evalf()) ** 2 - - -# progress: 2023-10-09 -# finished test on quantumsim and Tequila. -class Test_backends: - def test_basic(self): - def single(BackendClass, type, qisa, is_sim): - sim = BackendClass() - assert sim.get_type() == type - assert sim.get_qisa() == qisa - assert sim.is_simulator() == is_sim - - # QuaLeSim_tequila and QuaLeSim_quantumsim default Qisa type is QCIS - # single(QuaLeSim_tequila, BackendType.QUALESIM_TEQUILA, Qisa.QCIS, True) - single(QuaLeSim_quantumsim, BackendType.QUALESIM_QUANTUMSIM, Qisa.QCIS, True) - single(PyQCISim_tequila, BackendType.TEQUILA, Qisa.QCIS, True) - single(PyQCISim_quantumsim, BackendType.QUANTUM_SIM, Qisa.QCIS, True) - single(IfSymQC, BackendType.SYMQC, Qisa.QCIS, True) - - def test_upload_program(self): - def single(BackendClass, qasm_fn): - sim = BackendClass() - try: - sim.upload_program(qasm_fn) - except Exception as e: - assert False, "upload_program failed: {}".format(e) - - # single(QuaLeSim_tequila, qcis_fn) - # single(QuaLeSim_tequila, quiet_fn) - single(QuaLeSim_quantumsim, qcis_fn) - single(QuaLeSim_quantumsim, quiet_fn) - single(PyQCISim_tequila, qcis_fn) - single(PyQCISim_quantumsim, qcis_fn) - single(IfSymQC, qcis_fn) - - def test_execute(self): - def single(BackendClass, qasm_fn): - sim = BackendClass() - sim.upload_program(qasm_fn) - exe_config = ExeConfig(ExeMode.SimFinalResult, 10) - res = sim.execute(exe_config) - print(res) - # assert len(res) == 2 - # assert res[0] == ["Q1", "Q2"] - # assert all(v in [[0, 0], [1, 1]] for v in res[1]) - - # single(QuaLeSim_tequila, qcis_fn) - single(QuaLeSim_quantumsim, qcis_fn) - # single(QuaLeSim_tequila, quiet_fn) - single(QuaLeSim_quantumsim, quiet_fn) - single(PyQCISim_tequila, qcis_fn) - single(PyQCISim_quantumsim, qcis_fn) - single(IfSymQC, qcis_fn) - - def test_shots(self): - def single(BackendClass, qasm_fn): - random_vals = [3, 10, 100] - for num_rep in random_vals: - sim = BackendClass() - sim.upload_program(qasm_fn) - exe_config = ExeConfig(ExeMode.SimFinalResult, num_rep) - res = sim.execute(exe_config) - assert res[0] == ["Q1", "Q2"] - assert len(res[1]) == num_rep - assert all(v in [[0, 0], [1, 1]] for v in res[1]) - - # single(QuaLeSim_tequila, qcis_fn) - single(QuaLeSim_quantumsim, qcis_fn) - # single(QuaLeSim_tequila, quiet_fn) - single(QuaLeSim_quantumsim, quiet_fn) - single(PyQCISim_tequila, qcis_fn) - single(PyQCISim_quantumsim, qcis_fn) - single(IfSymQC, qcis_fn) - - def test_get_from_hub(self): - def single(backend_type, qasm_fn): - hub = Backend_hub() - sim = hub.get_instance(backend_type) - sim.upload_program(qasm_fn) - exe_config = ExeConfig(ExeMode.SimFinalResult, 10) - res = sim.execute(exe_config) - assert res[0] == ["Q1", "Q2"] - assert len(res[1]) == 10 - assert all(v in [[0, 0], [1, 1]] for v in res[1]) - - # single(BackendType.QUALESIM_TEQUILA, qcis_fn) - single(BackendType.QUALESIM_QUANTUMSIM, qcis_fn) - # single(BackendType.QUALESIM_TEQUILA, quiet_fn) - single(BackendType.QUALESIM_QUANTUMSIM, quiet_fn) - single(BackendType.TEQUILA, qcis_fn) - single(BackendType.QUANTUM_SIM, qcis_fn) - single(BackendType.SYMQC, qcis_fn) - - def test_state_vector(self): - def single(backend_type, qasm_fn): - hub = Backend_hub() - sim = hub.get_instance(backend_type) - sim.upload_program(qasm_fn) - exe_config = ExeConfig(ExeMode.SimStateVector) - res = sim.execute(exe_config) - a = res["quantum"][1][0] - b = res["quantum"][1][3] - - assert res["quantum"][0] == ["Q1", "Q2"] - assert dist(a, b) <= 0.01 - - # single(BackendType.QUALESIM_TEQUILA, quiet_fn2) - single(BackendType.QUALESIM_QUANTUMSIM, quiet_fn2) - # single(BackendType.QUALESIM_TEQUILA, qcis_fn) - single(BackendType.QUALESIM_QUANTUMSIM, qcis_fn) - single(BackendType.QUANTUM_SIM, qcis_fn2) - single(BackendType.SYMQC, qcis_fn2) - - def single_sim(backend_type, qcis_fn, exp_res): - hub = Backend_hub() - sim = hub.get_instance(backend_type) - sim.upload_program(qcis_fn) - exe_config = ExeConfig(ExeMode.SimFinalResult) - sim_result = sim.execute(exe_config) - _, msmt_res = sim_result - res = msmt_res[0] - res.reverse() - int_res = int("".join(map(str, res)), 2) - assert int_res == exp_res - - def test_sim_in_paral(self): - def single(backend_type): - qcis_2_fn = cur_dir / "test_qcis" / "mod_adder_nc_res_2.qcis" - qcis_5_fn = cur_dir / "test_qcis" / "mod_adder_nc_res_5.qcis" - - t1 = threading.Thread( - target=Test_backends.single_sim, - args=(backend_type, qcis_2_fn, 2), - ) - t2 = threading.Thread( - target=Test_backends.single_sim, - args=(backend_type, qcis_5_fn, 5), - ) - t1.start() - t2.start() - - # single(BackendType.QUALESIM_TEQUILA) - single(BackendType.QUALESIM_QUANTUMSIM) - single(BackendType.QUANTUM_SIM) - single(BackendType.TEQUILA) - - -if __name__ == "__main__": - test = Test_backends() - # test.test_basic() - # test.test_upload_program() - # test.test_execute() - # test.test_shots() - # test.test_get_from_hub() - test.test_state_vector() - # test.test_sim_in_paral() diff --git a/unittest/test_compile_cmd.py b/unittest/test_compile_cmd.py index ff8ca7d..e950c9b 100644 --- a/unittest/test_compile_cmd.py +++ b/unittest/test_compile_cmd.py @@ -3,10 +3,10 @@ from quingo.core.quingo_task import * from pathlib import Path from quingo.core.compile import * from quingo.core.compiler_config import get_mlir_path -from global_config import SRC_PATH -cur_dir = SRC_PATH / "unittest" / "" -qu_dir = cur_dir / "test_qu" / "" +unittest_dir = Path(__file__).parent +qu_dir = unittest_dir / "test_qu" +mock_qcis_fn = unittest_dir / "mock.qcis" class TestGetMlirPath: @@ -19,22 +19,12 @@ class TestCompileCmd: def test_gen_default(self): mock_fn = qu_dir / "mock.qu" task = Quingo_task(mock_fn, "foo") + + qasm_fn = compile(task, params=(1, 2), qasm_fn=mock_qcis_fn) + mlir_path = Path(get_mlir_path()) - qasm_fn = compile( - task, - ( - 1, - 2, - ), - qasm_fn=cur_dir / "mock.qcis", - ) - cmd = compose_cl_cmd( - task, - qasm_fn, - mlir_path, - ) + cmd = compose_cl_cmd(task, qasm_fn, mlir_path) cmd_eles = cmd.split() - print(cmd_eles) assert len(cmd_eles) == 10 assert mlir_path.resolve().samefile(cmd_eles[0].strip('"')) assert cmd_eles[1] == '"{}"'.format(task.cl_entry_fn.resolve()) @@ -46,7 +36,7 @@ class TestCompileCmd: def test_compile(self): bell_fn = qu_dir / "bell.qu" - task = Quingo_task(bell_fn, "bell") + task = Quingo_task(bell_fn, "bell", debug_mode=True) qasm_fn = compile(task, ()) with qasm_fn.open("r") as f: lines = f.readlines() @@ -56,8 +46,8 @@ class TestCompileCmd: def test_compile2(self): bell_fn = qu_dir / "bell.qu" task = Quingo_task(bell_fn, "bell") - qasm_fn = compile(task, (), qasm_fn=cur_dir / "out_bell.qcis") - assert qasm_fn.samefile(cur_dir / "out_bell.qcis") + qasm_fn = compile(task, (), qasm_fn=unittest_dir / "out_bell.qcis") + assert qasm_fn.samefile(unittest_dir / "out_bell.qcis") with qasm_fn.open("r") as f: lines = f.readlines() assert lines[0].strip() == "H Q0" @@ -66,6 +56,6 @@ class TestCompileCmd: if __name__ == "__main__": # TestGetMlirPath().test_get_path() - TestCompileCmd().test_gen_default() - # TestCompileCmd().test_compile() + # TestCompileCmd().test_gen_default() + TestCompileCmd().test_compile() # TestCompileCmd().test_compile2() diff --git a/unittest/test_execution.py b/unittest/test_execution.py index f450279..c24dff4 100644 --- a/unittest/test_execution.py +++ b/unittest/test_execution.py @@ -1,35 +1,31 @@ from pathlib import Path -from quingo.core.manager import call, compile, execute -from quingo.core.exe_config import * -from quingo.core.quingo_task import Quingo_task -from quingo.backend.backend_hub import BackendType, Backend_hub -from global_config import SRC_PATH +from quingo import BackendType, Quingo_task, ExeConfig, ExeMode +from quingo import call, compile, execute -cur_dir = SRC_PATH / "unittest" / "" -qu_file = cur_dir / "test_qu" / "bell.qu" +unittest_dir = Path(__file__).parent +qu_file = unittest_dir / "test_qu" / "bell.qu" -class Test_execution: - def test_execute(self): - task = Quingo_task(qu_file, "bell") - num_shot = 4 - cfg = ExeConfig(ExeMode.SimFinalResult, num_shot) - qasm_fn = compile(task, params=()) - res = execute(qasm_fn, BackendType.QUANTUM_SIM, cfg) +def test_compile_execute(): + task = Quingo_task(qu_file, "bell") + num_shot = 4 + cfg = ExeConfig(ExeMode.SimShots, num_shot) + qasm_fn = compile(task, params=()) + res = execute(qasm_fn, BackendType.QUANTUM_SIM, cfg) - assert len(res[0]) == 2 - assert len(res[1]) == 4 + assert len(res[0]) == 2 + assert len(res[1]) == 4 - def test_call(self): - task = Quingo_task(qu_file, "bell") - cfg = ExeConfig(ExeMode.SimFinalResult, 4) - res = call(task, (), BackendType.QUANTUM_SIM, cfg) - assert len(res[0]) == 2 - assert len(res[1]) == 4 +def test_call(): + task = Quingo_task(qu_file, "bell") + cfg = ExeConfig(ExeMode.SimShots, 4) + res = call(task, (), BackendType.QUANTUM_SIM, cfg) + + assert len(res[0]) == 2 + assert len(res[1]) == 4 if __name__ == "__main__": - test = Test_execution() - test.test_execute() - test.test_call() + test_compile_execute() + test_call() diff --git a/unittest/test_preparation.py b/unittest/test_preparation.py index d158f5d..2dccdc6 100644 --- a/unittest/test_preparation.py +++ b/unittest/test_preparation.py @@ -1,10 +1,9 @@ import pytest from quingo.core.preparation import * from pathlib import Path -from global_config import SRC_PATH -cur_dir = SRC_PATH / "unittest" / "" -qu_dir = cur_dir / "test_qu" / "" +unittest_dir = Path(__file__).parent +qu_dir = unittest_dir / "test_qu" class TestPrepareMain: diff --git a/unittest/test_qcis/bell.qi b/unittest/test_qcis/bell.qi index c41e1c5..8a8cbd6 100644 --- a/unittest/test_qcis/bell.qi +++ b/unittest/test_qcis/bell.qi @@ -1,9 +1,9 @@ .body: - func main()->(int c1, int c2): + func main() -> (int c1, int c2): qubit Q1 qubit Q2 H Q1 CNOT Q1, Q2 - measure(Q1)->c1 - measure(Q2)->c2 + measure(Q1) -> c1 + measure(Q2) -> c2 end \ No newline at end of file diff --git a/unittest/test_qcis/bell_copy.qcis b/unittest/test_qcis/bell_no_msmt.qcis similarity index 100% rename from unittest/test_qcis/bell_copy.qcis rename to unittest/test_qcis/bell_no_msmt.qcis diff --git a/unittest/test_qcis/bell_copy.qi b/unittest/test_qcis/bell_no_msmt.qi similarity index 100% rename from unittest/test_qcis/bell_copy.qi rename to unittest/test_qcis/bell_no_msmt.qi diff --git a/unittest/test_quingo_task.py b/unittest/test_quingo_task.py index 1e229cc..6b11554 100644 --- a/unittest/test_quingo_task.py +++ b/unittest/test_quingo_task.py @@ -4,11 +4,10 @@ from quingo.backend.backend_hub import BackendType from quingo.backend.qisa import Qisa from pathlib import Path import platform -from global_config import SRC_PATH -cur_dir = SRC_PATH / "unittest" / "" -qu_dir = cur_dir / "test_qu" / "" +unittest_dir = Path(__file__).parent +qu_dir = unittest_dir / "test_qu" class TestQuingoTask: diff --git a/unittest/test_result.py b/unittest/test_result.py deleted file mode 100644 index d60f4f1..0000000 --- a/unittest/test_result.py +++ /dev/null @@ -1,76 +0,0 @@ -# from quingo.backend.qualesim_tequila import QuaLeSim_tequila -# from quingo.backend.qualesim_quantumsim import QuaLeSim_quantumsim -from quingo.backend.pyqcisim_quantumsim import PyQCISim_quantumsim -from quingo.backend.pyqcisim_tequila import PyQCISim_tequila -from quingo.backend.symqc import IfSymQC -from quingo.backend.backend_hub import BackendType, Backend_hub -from quingo.backend.qisa import Qisa -from quingo.core.exe_config import * -from pathlib import Path -import sympy -import threading -import random -from global_config import SRC_PATH - -cur_dir = SRC_PATH / "unittest" / "" -qcis_fn = cur_dir / "test_qcis" / "bell.qcis" -qcis_fn2 = cur_dir / "test_qcis" / "bell_copy.qcis" -quiet_fn = cur_dir / "test_qcis" / "bell.qi" -quiet_fn2 = cur_dir / "test_qcis" / "bell_copy.qi" - - -def is_similar_statevector(m1, m2): - if isinstance(m1, sympy.matrices.dense.MutableDenseMatrix): - m1 = [complex(i.evalf()) for i in m1] - if isinstance(m2, sympy.matrices.dense.MutableDenseMatrix): - m2 = [complex(i.evalf()) for i in m2] - dist = 0 - for i in range(len(m1)): - dist = dist + (m1[i].real - m2[i].real) ** 2 + (m1[i].imag - m2[i].imag) ** 2 - return dist <= 1e-5 - - -class Test_backends: - def test_one_shot_res(self): - def single(BackendClass, qasm_fn, num_shots): - sim = BackendClass() - sim.upload_program(qasm_fn) - exe_config = ExeConfig(ExeMode.SimFinalResult, num_shots) - res = sim.execute(exe_config) - assert isinstance(res, tuple) - assert len(res) == 2 - assert res[0] == ["Q1", "Q2"] - assert len(res[1]) == num_shots - assert all(v in [[0, 0], [1, 1]] for v in res[1]) - return res - - # res1 = single(QuaLeSim_quantumsim, qcis_fn, 10) - # res2 = single(QuaLeSim_tequila, qcis_fn, 8) - res1 = single(PyQCISim_quantumsim, qcis_fn, 10) - res2 = single(PyQCISim_tequila, qcis_fn, 8) - res3 = single(IfSymQC, qcis_fn, 1) - assert res1[0] == res2[0] - assert res2[0] == res3[0] - - def test_state_vector_res(self): - def single(BackendClass, qasm_fn): - sim = BackendClass() - sim.upload_program(qasm_fn) - exe_config = ExeConfig(ExeMode.SimStateVector) - res = sim.execute(exe_config) - print(res) - assert res["quantum"][0] == ["Q1", "Q2"] - return res - - # res1 = single(QuaLeSim_tequila, qcis_fn) - # res2 = single(QuaLeSim_quantumsim, qcis_fn) - res1 = single(PyQCISim_quantumsim, qcis_fn2) - res3 = single(IfSymQC, qcis_fn2) - # assert is_similar_statevector(res1["quantum"][1], res2["quantum"][1]) - assert is_similar_statevector(res1["quantum"][1], res3["quantum"][1]) - - -if __name__ == "__main__": - test = Test_backends() - test.test_one_shot_res() - # test.test_state_vector_res() -- Gitee From a6c464dda809be07adc906dc75e6c071a317e5a4 Mon Sep 17 00:00:00 2001 From: Xiang Fu Date: Tue, 16 Apr 2024 21:38:12 +0800 Subject: [PATCH 04/13] =?UTF-8?q?=E2=9C=A8=20feat(backend):=20update=20res?= =?UTF-8?q?ult=20formatter?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/adder/adder.py | 28 ------ src/quingo/backend/pyqcisim_quantumsim.py | 2 +- src/quingo/backend/result_formatter.py | 96 +++++++++++++++---- unittest/backends/test_result_formatter.py | 105 +++++++++++++++++++++ unittest/test_utils.py | 40 -------- 5 files changed, 185 insertions(+), 86 deletions(-) create mode 100644 unittest/backends/test_result_formatter.py delete mode 100644 unittest/test_utils.py diff --git a/examples/adder/adder.py b/examples/adder/adder.py index b9072e9..823bea3 100755 --- a/examples/adder/adder.py +++ b/examples/adder/adder.py @@ -10,34 +10,6 @@ from my_utils import * sys.path.append(dirname(dirname(abspath(__file__)))) -def get_first_non_zero_res(sim_result, integer_format=True): - """This function is used to get the first non-zero result from the measurement results. - - sim_result format: (qubit_list, msmt res list). - An Example result of a simulation with num_shots=3: - ``` - (['Q3', 'Q4', 'Q5', 'Q6', 'Q7'], - [[1, 1, 0, 0, 0], - [1, 1, 0, 0, 0], - [1, 1, 0, 0, 0]]) - ``` - return: the first non-zero result (in integer format) in the measurement results. - """ - if sim_result is None: - raise ValueError("No measure results found") - _, msmt_res = sim_result - - if msmt_res is None: - raise ValueError("No measure results found") - - res = msmt_res[0] - res.reverse() - if integer_format: - return int("".join(map(str, res)), 2) - else: - return msmt_res[0] - - logger = get_logger("adder_test") logger.setLevel(logging.INFO) diff --git a/src/quingo/backend/pyqcisim_quantumsim.py b/src/quingo/backend/pyqcisim_quantumsim.py index 4628c94..fcb39de 100755 --- a/src/quingo/backend/pyqcisim_quantumsim.py +++ b/src/quingo/backend/pyqcisim_quantumsim.py @@ -42,7 +42,7 @@ class PyQCISim_quantumsim(If_backend): if exe_config.mode == ExeMode.SimStateVector: raw_res = self.sim.simulate("state_vector") - return raw_res["quantum"] + return raw_res raise ValueError( "Unsupported execution mode ({}) for quantumsim.".format(exe_config.mode) diff --git a/src/quingo/backend/result_formatter.py b/src/quingo/backend/result_formatter.py index c9bc9c7..667fb3d 100644 --- a/src/quingo/backend/result_formatter.py +++ b/src/quingo/backend/result_formatter.py @@ -1,31 +1,93 @@ -def reorder_bits(qubit_list, str_bit_list, Ascending=True): - """Reorder the bits in str_bit_list according to the order of qubit_list. - Given qubit list ["Q2", "Q1", "Q4", "Q3"] and `str_bit_list` "0001", - the ordered result is "0010", which corresponds to ["Q1", "Q2", "Q3", "Q4"]. +from typing import List, Tuple + + +def reorder_bits(qubit_list, qubit_msmt_res, Ascending=True): """ + Given the measurement result `qubit_msmt_res` of `qubit_list`, reorder the bits in the + result according to the qubit name order. + + Args: + qubit_list (list): A list of qubit names in the desired order. + qubit_msmt_res (list): A list of measurement results corresponding to the qubits. + Ascending (bool, optional): Specifies whether the bits should be reordered in ascending order. + Defaults to True. + + Returns: + list: A list of reordered measurement results. + Example: + Given qubit list ["Q3", "Q1", "Q4", "Q2"] and `qubit_msmt_res` [1, 1, 0, 0], + the ordered result is [1, 0, 1, 0], which corresponds to ["Q1", "Q2", "Q3", "Q4"]. + """ num_qubits = len(qubit_list) - qubit_result_pair = [(qubit_list[i], str_bit_list[i]) for i in range(num_qubits)] + qubit_result_pair = [ + (qubit_list[i].lower(), qubit_msmt_res[i]) for i in range(num_qubits) + ] qubit_result_pair.sort(key=lambda x: int(x[0][1:]), reverse=not Ascending) print(qubit_result_pair) - return "".join([x[1] for x in qubit_result_pair]) + return [x[1] for x in qubit_result_pair] + + +def get_first_non_zero_res( + shots_result: Tuple[List[str], List[List[int]]], + qubits: List[str] = None, + integer_format=True, + little_endian=True, +): + """ + This function is used to get the first non-zero result from the measurement results. + + Args: + shots_result (tuple): A tuple containing two elements: a list of qubit names and a list + of measurement results. + An example shots result of a simulation with num_shots = 3: + (['Q3', 'Q4', 'Q5', 'Q6', 'Q7'], + [[1, 1, 0, 0, 0], + [1, 1, 0, 0, 0], + [1, 1, 0, 0, 0]]) + qubits (list, optional): A list of qubit names. If provided, the function will only consider + the measurement results of the specified qubits. + Defaults to None. -def get_first_non_zero_res(qcis_result): - """This function is used to get the first non-zero result from the measurement results. + integer_format (bool, optional): Specifies whether the result should be returned as an + integer or as a list of bits. + Defaults to True. - qcis_result format: (qubit_list, msmt_count), where qubit_list is a list of qubit names, and msmt_count is a dictionary of measurement results. + little_endian (bool, optional): Specifies whether the result should be in little-endian + format. If False, the result is in big-endian format. + Defaults to True. + Little-endian: [Q0, Q1, Q2] [1, 0, 0] -> 1 + Big-endian: [Q0, Q1, Q2] [1, 0, 0] -> 4 - return: the first non-zero result (in integer format) in the measurement results. + Returns: + int or list: The first non-zero result in the measurement results. If `integer_format` is + True, the result is returned as an integer. + Otherwise, the result is returned as a list of bits. + + Raises: + ValueError: If `shots_result` is None or if the measurement results are None. """ - if qcis_result is None: - print("No measure results found") - qubit_list, msmt_count = qcis_result - for k, v in msmt_count.items(): - if v > 0: - ordered_str = reorder_bits(qubit_list, k) - return int(ordered_str, 2) + if shots_result is None: + raise ValueError("No measure results found") + names, msmt_res = shots_result + + if msmt_res is None: + raise ValueError("No measure results found") + + res = msmt_res[0] + if qubits is not None: + indices = [names.index(q) for q in qubits] + res = [res[idx] for idx in indices] + + if little_endian: + res.reverse() + + if integer_format: + return int("".join(map(str, res)), 2) + else: + return msmt_res[0] diff --git a/unittest/backends/test_result_formatter.py b/unittest/backends/test_result_formatter.py new file mode 100644 index 0000000..8288e04 --- /dev/null +++ b/unittest/backends/test_result_formatter.py @@ -0,0 +1,105 @@ +import unittest +from quingo.backend.result_formatter import get_first_non_zero_res, reorder_bits + + +class TestResultFormatter(unittest.TestCase): + def test_no_measure_results(self): + with self.assertRaises(ValueError): + get_first_non_zero_res(None) + + def test_no_measure_results_found(self): + shots_result = (["Q3", "Q4", "Q5", "Q6", "Q7"], None) + with self.assertRaises(ValueError): + get_first_non_zero_res(shots_result) + + def test_integer_format_little_endian(self): + shots_result = ( + ["Q3", "Q4", "Q5", "Q6", "Q7"], + [[1, 1, 0, 0, 0], [1, 1, 0, 0, 0], [1, 1, 0, 0, 0]], + ) + result = get_first_non_zero_res(shots_result) + self.assertEqual(result, 0b00011) + + def test_integer_format_big_endian(self): + shots_result = ( + ["Q3", "Q4", "Q5", "Q6", "Q7"], + [[1, 1, 0, 0, 0], [1, 1, 0, 0, 0], [1, 1, 0, 0, 0]], + ) + result = get_first_non_zero_res(shots_result, little_endian=False) + self.assertEqual(result, 0b11000) + + def test_list_format_little_endian(self): + shots_result = ( + ["Q3", "Q4", "Q5", "Q6", "Q7"], + [[1, 1, 0, 0, 0], [1, 1, 0, 0, 0], [1, 1, 0, 0, 0]], + ) + result = get_first_non_zero_res(shots_result, integer_format=False) + self.assertEqual(result, [0, 0, 0, 1, 1]) + + def test_list_format_big_endian(self): + shots_result = ( + ["Q3", "Q4", "Q5", "Q6", "Q7"], + [[1, 1, 0, 0, 0], [1, 1, 0, 0, 0], [1, 1, 0, 0, 0]], + ) + result = get_first_non_zero_res( + shots_result, integer_format=False, little_endian=False + ) + self.assertEqual(result, [1, 1, 0, 0, 0]) + + def test_specific_qubits(self): + shots_result = ( + ["Q3", "Q4", "Q5", "Q6", "Q7"], + [[1, 1, 0, 0, 0], [1, 1, 0, 0, 0], [1, 1, 0, 0, 0]], + ) + result = get_first_non_zero_res(shots_result, qubits=["Q4", "Q5"]) + self.assertEqual(result, 0b01) + + def test_reorder_bits_ascending(self): + qubit_list = ["Q3", "Q1", "Q4", "Q2"] + qubit_msmt_res = [1, 1, 0, 0] + expected_result = [1, 0, 1, 0] + result = reorder_bits(qubit_list, qubit_msmt_res) + self.assertEqual(result, expected_result) + + def test_reorder_bits_descending(self): + qubit_list = ["Q3", "Q1", "Q4", "Q2"] + qubit_msmt_res = [1, 1, 0, 0] + expected_result = [0, 1, 0, 1] + result = reorder_bits(qubit_list, qubit_msmt_res, Ascending=False) + self.assertEqual(result, expected_result) + + def test_reorder_bits_same_order(self): + qubit_list = ["Q1", "Q2", "Q3", "Q4"] + qubit_msmt_res = [1, 0, 1, 0] + expected_result = [1, 0, 1, 0] + self.assertEqual( + reorder_bits(qubit_list, qubit_msmt_res, Ascending=True), expected_result + ) + + def test_reorder_bits_empty_input(self): + qubit_list = [] + qubit_msmt_res = [] + expected_result = [] + self.assertEqual( + reorder_bits(qubit_list, qubit_msmt_res, Ascending=True), expected_result + ) + + def test_reorder_bits_more_qubits(self): + qubit_list = ["Q6", "Q3", "Q1", "Q4", "Q2", "Q5"] + qubit_msmt_res = [1, 1, 0, 0, 1, 0] + expected_result = [0, 1, 1, 0, 0, 1] + self.assertEqual( + reorder_bits(qubit_list, qubit_msmt_res, Ascending=True), expected_result + ) + + def test_reorder_bits_fewer_qubits(self): + qubit_list = ["Q2", "Q1"] + qubit_msmt_res = [1, 0] + expected_result = [0, 1] + self.assertEqual( + reorder_bits(qubit_list, qubit_msmt_res, Ascending=True), expected_result + ) + + +if __name__ == "__main__": + unittest.main() diff --git a/unittest/test_utils.py b/unittest/test_utils.py deleted file mode 100644 index a5e1c2f..0000000 --- a/unittest/test_utils.py +++ /dev/null @@ -1,40 +0,0 @@ -import quingo.backend.result_formatter as rf - - -class Test_result_formater: - def test_reorder_bits(self): - def single_test_case(qubit_list, str_bit_list, expected): - res = rf.reorder_bits(qubit_list, str_bit_list) - print(res) - assert res == expected - - qubit_list = ["Q1", "Q2", "Q3", "Q4"] - single_test_case(qubit_list, "0001", "0001") - single_test_case(qubit_list, "0010", "0010") - single_test_case(qubit_list, "0100", "0100") - single_test_case(qubit_list, "1000", "1000") - qubit_list = ["Q2", "Q1", "Q4", "Q3"] - single_test_case(qubit_list, "0001", "0010") - single_test_case(qubit_list, "0010", "0001") - single_test_case(qubit_list, "0100", "1000") - single_test_case(qubit_list, "1000", "0100") - qubit_list = ["Q2", "Q4", "Q3", "Q1"] - single_test_case(qubit_list, "1001", "1100") - single_test_case(qubit_list, "0001", "1000") - single_test_case(qubit_list, "0110", "0011") - single_test_case(qubit_list, "0100", "0001") - - qubit_list = ["Q3", "Q4", "Q5", "Q6", "Q7"] - single_test_case(qubit_list, "00011", "00011") - single_test_case(qubit_list, "01100", "01100") - single_test_case(qubit_list, "11000", "11000") - - qubit_list = ["Q6", "Q8", "Q2", "Q4", "Q9"] - single_test_case(qubit_list, "00011", "01001") - single_test_case(qubit_list, "01100", "10010") - single_test_case(qubit_list, "11000", "00110") - - -if __name__ == "__main__": - test = Test_result_formater() - test.test_reorder_bits() -- Gitee From a72bf71de3b61c15ea8253e388f4404a8c2d1cc5 Mon Sep 17 00:00:00 2001 From: Xiang Fu Date: Wed, 17 Apr 2024 14:35:27 +0800 Subject: [PATCH 05/13] =?UTF-8?q?=F0=9F=A6=84=20refactor(*):=20rename=20fi?= =?UTF-8?q?le=20for=20the=20logger=20system?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/adder/my_utils.py | 74 --------------- examples/bell_state/host.py | 8 +- src/quingo/backend/if_backend.py | 6 +- src/quingo/backend/pyqcisim_quantumsim.py | 11 ++- src/quingo/backend/pyqcisim_tequila.py | 12 ++- src/quingo/backend/qualesim_quantumsim.py | 11 +-- src/quingo/backend/symqc.py | 7 +- src/quingo/backend/xiaohong.py | 11 +-- src/quingo/core/compile.py | 9 +- src/quingo/core/compiler_config.py | 2 +- src/quingo/core/data_transfer.py | 3 +- src/quingo/core/manager.py | 49 +++++++--- src/quingo/core/preparation.py | 3 +- .../core/{utils.py => quingo_logger.py} | 8 -- src/quingo/core/quingo_task.py | 2 +- src/quingo/utils.py | 34 +++++++ unittest/backends/test_result_format.py | 89 ++++++------------- 17 files changed, 139 insertions(+), 200 deletions(-) rename src/quingo/core/{utils.py => quingo_logger.py} (89%) diff --git a/examples/adder/my_utils.py b/examples/adder/my_utils.py index 78a1f11..6caa5e7 100755 --- a/examples/adder/my_utils.py +++ b/examples/adder/my_utils.py @@ -9,14 +9,6 @@ def subtracter_behavior(a, b, num_qubits): return (1 << num_qubits) - (b - a) -def is_number(s): - try: - float(s) - return True - except ValueError: - return False - - def get_bin(x, n): if not is_number(x): raise ValueError("get_bin: parameter is not a number.") @@ -42,71 +34,5 @@ def test_int2bits(): assert int2bit_list(1089, 15) == [1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0] -import logging -from logging.handlers import TimedRotatingFileHandler -import sys -import colorama as cm -import termcolor as tc -from pathlib import Path - -cm.init() - -# Fore: BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE, RESET. -# Back: BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE, RESET. -# Style: DIM, NORMAL, BRIGHT, RESET_ALL - - -def quingo_info(arg, **kwargs): - print(arg, **kwargs) - - -def quingo_msg(arg, **kwargs): - print(tc.colored(arg, "green"), **kwargs) - - -def quingo_warning(arg, **kwargs): - print(tc.colored(arg, "yellow"), **kwargs) - - -def quingo_err(arg, **kwargs): - print(tc.colored(arg, "red"), **kwargs) - - -FORMATTER = logging.Formatter( - "%(asctime)s %(name)s %(lineno)d(%(levelname)s): %(message)s", datefmt="%H:%M:%S" -) -# LOG_FILE = "my_app.log" - - -def get_console_handler(): - console_handler = logging.StreamHandler(sys.stdout) - console_handler.setFormatter(FORMATTER) - return console_handler - - -# def get_file_handler(): -# file_handler = TimedRotatingFileHandler(LOG_FILE, when='midnight') -# file_handler.setFormatter(FORMATTER) -# return file_handler - - -def get_logger(logger_name): - logger = logging.getLogger(logger_name) - # better to have too much log than not enough - logger.setLevel(logging.DEBUG) - logger.addHandler(get_console_handler()) - # logger.addHandler(get_file_handler()) - # with this pattern, it's rarely necessary to propagate the error up to parent - logger.propagate = False - return logger - - -def ensure_path(fn) -> Path: - assert isinstance(fn, (str, Path)) - if isinstance(fn, str): - fn = Path(fn).resolve() - return fn - - if __name__ == "__main__": test_int2bits() diff --git a/examples/bell_state/host.py b/examples/bell_state/host.py index 450a935..18b9d23 100644 --- a/examples/bell_state/host.py +++ b/examples/bell_state/host.py @@ -9,8 +9,12 @@ def routine(circ_name, num_shots=1): task = Quingo_task(qu_file, circ_name) cfg = ExeConfig(ExeMode.SimFinalResult, num_shots=num_shots) qasm_fn = compile(task, params=(), config_file="") - res = execute(qasm_fn, BackendType.QUALESIM_QUANTUMSIM, cfg) # QuantumSim, SymQC - print("sim res: ", res) + sim_result = execute(qasm_fn, BackendType.QUALESIM_QUANTUMSIM, cfg) + print(sim_result) + names, values = sim_result + # print("sim res: ", res) + print("names: ", names) + print("values ({}): ".format(type(values)), values) routine("bell_state", 10) diff --git a/src/quingo/backend/if_backend.py b/src/quingo/backend/if_backend.py index 11898b0..35543fc 100755 --- a/src/quingo/backend/if_backend.py +++ b/src/quingo/backend/if_backend.py @@ -1,9 +1,5 @@ -import re -from quingo.core.utils import * -import logging -from pathlib import Path from .backend_hub import BackendType, Backend_hub -from quingo.core.exe_config import * +from quingo.core.exe_config import ExeConfig class If_backend: diff --git a/src/quingo/backend/pyqcisim_quantumsim.py b/src/quingo/backend/pyqcisim_quantumsim.py index fcb39de..5f3c7e8 100755 --- a/src/quingo/backend/pyqcisim_quantumsim.py +++ b/src/quingo/backend/pyqcisim_quantumsim.py @@ -1,7 +1,12 @@ +from __future__ import annotations +from numpy.typing import NDArray +from typing import List, Union + + +from quingo.utils import ensure_path from .backend_hub import BackendType from .if_backend import If_backend -from quingo.core.exe_config import * -from quingo.core.utils import * +from quingo.core.exe_config import ExeMode, ExeConfig from pyqcisim.simulator import PyQCISim @@ -24,7 +29,7 @@ class PyQCISim_quantumsim(If_backend): program = prog_fn.open("r").read() self.sim.compile(program) - def execute(self, exe_config: ExeConfig): + def execute(self, exe_config: ExeConfig) -> Union[List | NDArray]: """Execute the given quantum circuit. Args: - mode (str): the simulation mode to use: diff --git a/src/quingo/backend/pyqcisim_tequila.py b/src/quingo/backend/pyqcisim_tequila.py index c87add2..42a2005 100644 --- a/src/quingo/backend/pyqcisim_tequila.py +++ b/src/quingo/backend/pyqcisim_tequila.py @@ -1,10 +1,9 @@ +from quingo.utils import ensure_path from .backend_hub import BackendType from .if_backend import If_backend -from quingo.core.exe_config import * -from quingo.core.utils import * +from quingo.core.exe_config import ExeConfig, ExeMode from pyqcisim.simulator import PyQCISim - -logger = get_logger((__name__).split(".")[-1]) +import numpy as np class PyQCISim_tequila(If_backend): @@ -38,9 +37,8 @@ class PyQCISim_tequila(If_backend): return self.sim.simulate("final_result") if exe_config.mode == ExeMode.SimStateVector: - raw_res = self.sim.simulate("state_vector") - print("result from pyqcisim_tequila: ", raw_res) - return raw_res + names, nd_array_values = self.sim.simulate("state_vector") + return (names, nd_array_values) raise ValueError( "Unsupported execution mode ({}) for TEQUILA.".format(exe_config.mode) diff --git a/src/quingo/backend/qualesim_quantumsim.py b/src/quingo/backend/qualesim_quantumsim.py index e89b1fb..ae554e3 100644 --- a/src/quingo/backend/qualesim_quantumsim.py +++ b/src/quingo/backend/qualesim_quantumsim.py @@ -1,11 +1,8 @@ +from quingo.utils import ensure_path from .backend_hub import BackendType from .if_backend import If_backend -from quingo.core.exe_config import * -from quingo.core.utils import * -from qualesim.plugin import * -from qualesim.host import * - -logger = get_logger((__name__).split(".")[-1]) +from quingo.core.exe_config import ExeConfig, ExeMode +from qualesim.plugin import Simulator, Loglevel class QuaLeSim_quantumsim(If_backend): @@ -75,7 +72,7 @@ class QuaLeSim_quantumsim(If_backend): res = self.sim.run(measure_mod=measure_mod) self.sim.stop() final_state = eval(res["res"]) - return final_state + return final_state["quantum"] except Exception as e: raise ValueError( diff --git a/src/quingo/backend/symqc.py b/src/quingo/backend/symqc.py index 914e47c..8e39be1 100644 --- a/src/quingo/backend/symqc.py +++ b/src/quingo/backend/symqc.py @@ -1,13 +1,10 @@ +from quingo.utils import ensure_path from .backend_hub import BackendType from .if_backend import If_backend -from quingo.core.exe_config import * -from quingo.core.utils import * +from quingo.core.exe_config import ExeConfig, ExeMode from symqc.simulator import SymQC -logger = get_logger((__name__).split(".")[-1]) - - class IfSymQC(If_backend): """A functional QCIS simulation backend based on symbolic computation.""" diff --git a/src/quingo/backend/xiaohong.py b/src/quingo/backend/xiaohong.py index 5c3506d..d170d63 100644 --- a/src/quingo/backend/xiaohong.py +++ b/src/quingo/backend/xiaohong.py @@ -1,11 +1,8 @@ +from quingo.utils import ensure_path from .backend_hub import BackendType from .if_backend import If_backend -from quingo.core.exe_config import * -from quingo.core.utils import * -from pyezQ import * - - -logger = get_logger((__name__).split(".")[-1]) +from quingo.core.exe_config import ExeConfig, ExeMode +import pyezQ class XiaoHong(If_backend): @@ -59,7 +56,7 @@ class XiaoHong(If_backend): return result def set_account(self, login_key, machine_name): - self.account = Account(login_key=login_key, machine_name=machine_name) + self.account = pyezQ.Account(login_key=login_key, machine_name=machine_name) print(f"Set account successfully:") print(f" login key = {login_key[0:5]}" + "*" * (len(login_key) - 5)) print(f" machine name = {machine_name}") diff --git a/src/quingo/core/compile.py b/src/quingo/core/compile.py index cfe5bca..07d6c41 100644 --- a/src/quingo/core/compile.py +++ b/src/quingo/core/compile.py @@ -1,10 +1,11 @@ -import subprocess, logging from pathlib import Path -from .compiler_config import get_mlir_path +import subprocess, logging +from quingo.core.compiler_config import get_mlir_path from quingo.core.quingo_task import Quingo_task from quingo.core.preparation import gen_main_file -from quingo.core.utils import quingo_err, get_logger, ensure_path -from quingo.backend.qisa import * +from quingo.core.quingo_logger import quingo_err, get_logger +from quingo.utils import ensure_path +from quingo.backend.qisa import Qisa, get_qisa_name, get_suffix logger = get_logger((__name__).split(".")[-1]) diff --git a/src/quingo/core/compiler_config.py b/src/quingo/core/compiler_config.py index 4334d02..6be46f8 100644 --- a/src/quingo/core/compiler_config.py +++ b/src/quingo/core/compiler_config.py @@ -1,5 +1,5 @@ from pathlib import Path -from .utils import quingo_err, quingo_info +from quingo.core.quingo_logger import quingo_err, quingo_info import quingo.global_config as gc import distutils.spawn import requests diff --git a/src/quingo/core/data_transfer.py b/src/quingo/core/data_transfer.py index 96284cd..70ac595 100755 --- a/src/quingo/core/data_transfer.py +++ b/src/quingo/core/data_transfer.py @@ -4,7 +4,8 @@ import numpy import quingo.global_config as gc from quingo.core.data import Time -from quingo.core.utils import * +import logging +from quingo.core.quingo_logger import get_logger from typing import Tuple logger = get_logger((__name__).split(".")[-1]) diff --git a/src/quingo/core/manager.py b/src/quingo/core/manager.py index 88fc009..994550e 100755 --- a/src/quingo/core/manager.py +++ b/src/quingo/core/manager.py @@ -1,13 +1,16 @@ +from __future__ import annotations +from numpy.typing import NDArray +from typing import List, Union +import numpy as np +import array +import sympy as sp + from pathlib import Path -import quingo.core.data_transfer as dt -from .exe_config import * -from .quingo_task import Quingo_task -from .compile import compile -from .utils import get_logger -from quingo.backend.backend_hub import BackendType, Backend_hub -from quingo.backend.qisa import * -logger = get_logger((__name__).split(".")[-1]) +from quingo.core.exe_config import ExeConfig, ExeMode +from quingo.core.quingo_task import Quingo_task +from quingo.core.compile import compile +from quingo.backend.backend_hub import BackendType, Backend_hub def verify_backend_config(backend: BackendType, exe_config: ExeConfig) -> bool: @@ -20,7 +23,9 @@ def verify_backend_config(backend: BackendType, exe_config: ExeConfig) -> bool: return True -def execute(qasm_fn: Path, be_type: BackendType, exe_config: ExeConfig = ExeConfig()): +def execute( + qasm_fn: Path, be_type: BackendType, exe_config: ExeConfig = ExeConfig() +) -> Union[List | NDArray]: """Execute the quingo task on the specified backend and return the result.""" if not verify_backend_config(be_type, exe_config): @@ -30,7 +35,31 @@ def execute(qasm_fn: Path, be_type: BackendType, exe_config: ExeConfig = ExeConf backend = Backend_hub().get_instance(be_type) backend.upload_program(qasm_fn) - return backend.execute(exe_config) + result = backend.execute(exe_config) + if exe_config.mode == ExeMode.SimStateVector: + names, array_values = result + if len(names) == 0: + return ([], 1) + + if isinstance(array_values, list): + if len(array_values) == 0: + return ([], 1) + + array_values = np.array(array_values) + + elif isinstance(array_values, array.array): + array_values = np.array(array_values) + + elif isinstance(array_values, sp.Matrix): + array_values = np.array(array_values).astype(np.complex64) + + else: + assert isinstance(array_values, np.ndarray) + + array_values = array_values.flatten() + return (names, array_values) + + return result def call( diff --git a/src/quingo/core/preparation.py b/src/quingo/core/preparation.py index d3cdb10..d9ec44e 100644 --- a/src/quingo/core/preparation.py +++ b/src/quingo/core/preparation.py @@ -1,11 +1,10 @@ """The task of this module is to prepare the Quingo source file for the compilation. """ - import re from pathlib import Path -from quingo.core.utils import get_logger import logging +from quingo.core.quingo_logger import get_logger import quingo.core.data_transfer as dt logger = get_logger((__name__).split(".")[-1]) diff --git a/src/quingo/core/utils.py b/src/quingo/core/quingo_logger.py similarity index 89% rename from src/quingo/core/utils.py rename to src/quingo/core/quingo_logger.py index 27bf1ee..5ef257e 100755 --- a/src/quingo/core/utils.py +++ b/src/quingo/core/quingo_logger.py @@ -3,7 +3,6 @@ from logging.handlers import TimedRotatingFileHandler import sys import colorama as cm import termcolor as tc -from pathlib import Path cm.init() @@ -55,10 +54,3 @@ def get_logger(logger_name): # with this pattern, it's rarely necessary to propagate the error up to parent logger.propagate = False return logger - - -def ensure_path(fn) -> Path: - assert isinstance(fn, (str, Path)) - if isinstance(fn, str): - fn = Path(fn).resolve() - return fn diff --git a/src/quingo/core/quingo_task.py b/src/quingo/core/quingo_task.py index 9f0104e..01c9cc0 100644 --- a/src/quingo/core/quingo_task.py +++ b/src/quingo/core/quingo_task.py @@ -4,7 +4,7 @@ import quingo.global_config as gc import tempfile from quingo.backend.backend_hub import BackendType from quingo.backend.qisa import Qisa -from quingo.core.utils import ensure_path +from quingo.utils import ensure_path DEBUG_MODE = False diff --git a/src/quingo/utils.py b/src/quingo/utils.py index 1e20c67..67cfa2c 100644 --- a/src/quingo/utils.py +++ b/src/quingo/utils.py @@ -1,4 +1,21 @@ import sympy as sp +from pathlib import Path +import numpy as np + + +def ensure_path(fn) -> Path: + assert isinstance(fn, (str, Path)) + if isinstance(fn, str): + fn = Path(fn).resolve() + return fn + + +def is_number(s): + try: + float(s) + return True + except ValueError: + return False def singleton(cls): @@ -21,3 +38,20 @@ def number_distance(a, b): return (a.evalf() - b.evalf()) ** 2 raise ValueError("unsupported types for dist: {} and {}".format(type(a), type(b))) + + +import numpy as np + + +def state_fidelity(state_a: np.ndarray, state_b: np.ndarray): + """ + Calculate the state fidelity between two quantum states. + + Parameters: + state_a (np.ndarray): The first quantum state. + state_b (np.ndarray): The second quantum state. + + Returns: + float: The state fidelity between the two quantum states. + """ + return np.vdot(state_a, state_b) diff --git a/unittest/backends/test_result_format.py b/unittest/backends/test_result_format.py index d946aa7..a756e49 100644 --- a/unittest/backends/test_result_format.py +++ b/unittest/backends/test_result_format.py @@ -1,9 +1,10 @@ from quingo.backend.backend_hub import BackendType, Backend_hub from quingo.core.exe_config import ExeConfig, ExeMode from quingo import execute -from quingo.utils import number_distance +from quingo.utils import number_distance, state_fidelity from pathlib import Path import pytest +import numpy as np cur_dir = Path(__file__).parent @@ -75,65 +76,27 @@ def test_final_result_without_msmt(get_simulator, get_num_shots): print("result: ", result) -class TestStateVector: - """When simulating a quantum program in the state vector mode, - the result should be a tuple: - ( - ["Q1", "Q2"], - [0.7071067811865475, 0.0, 0.0, 0.7071067811865475] - ) - """ - - def vec_tests(self): - def vec_test_without_msmt(simulator): - exe_config = ExeConfig(ExeMode.SimStateVector) - state_vec_res = execute(bell_no_msmt_qcis_fn, simulator, exe_config) - assert len(state_vec_res) == 2 - assert state_vec_res[0] == ["Q1", "Q2"] - - assert len(state_vec_res[1]) == 4 - - vec_test_without_msmt(BackendType.TEQUILA) - vec_test_without_msmt(BackendType.QUANTUM_SIM) - vec_test_without_msmt(BackendType.SYMQC) - vec_test_without_msmt(BackendType.QUALESIM_QUANTUMSIM) - - def vec_tests_with_msmt(self): - - def vec_test_with_msmt(simulator): - exe_config = ExeConfig(ExeMode.SimStateVector) - state_vec_res = execute(bell_qcis_fn, simulator, exe_config) - assert len(state_vec_res) == 2 - assert state_vec_res[0] == ["Q1", "Q2"] - - assert len(state_vec_res[1]) == 4 - - vec_test_with_msmt(BackendType.TEQUILA) - vec_test_with_msmt(BackendType.QUANTUM_SIM) - vec_test_with_msmt(BackendType.SYMQC) - vec_test_with_msmt(BackendType.QUALESIM_QUANTUMSIM) - - def test_quantumsim_with_msmt(self): - exe_config = ExeConfig(ExeMode.SimStateVector) - state_vec_res = execute( - bell_no_msmt_qcis_fn, BackendType.QUANTUM_SIM, exe_config - ) - assert len(state_vec_res) == 2 - assert state_vec_res[0] == ["Q1", "Q2"] - - assert len(state_vec_res[1]) == 4 - - -if __name__ == "__main__": - # test_final_result_with_msmt() - test_shot_without_msmt(BackendType.QUANTUM_SIM, 10) - # test = TestFinalResult() - # # test.test_sim_with_msmt() - # # test.test_sim_without_msmt() - - # # test = TestStateVector() - # # test.test_symqc_with_msmt() - # # test.test_symqc_without_msmt() - # # test.test_quantumsim_with_msmt() - # test = TestShots() - # test.test_shots() +def test_state_vector_without_msmt(get_simulator): + simulator = get_simulator + exe_config = ExeConfig(ExeMode.SimStateVector) + qubit_names, state_vec = execute(bell_no_msmt_qcis_fn, simulator, exe_config) + + assert qubit_names == ["Q1", "Q2"] + assert isinstance(state_vec, (list, np.ndarray)) + assert state_vec.shape == (4,) + assert state_fidelity( + state_vec, [0.7071067811865475, 0.0, 0.0, 0.7071067811865475] + ) == pytest.approx(1) + + +def test_state_vector_with_msmt(get_simulator): + simulator = get_simulator + exe_config = ExeConfig(ExeMode.SimStateVector) + qubit_names, state_vec = execute(bell_qcis_fn, simulator, exe_config) + + assert qubit_names == ["Q1", "Q2"] + assert isinstance(state_vec, (list, np.ndarray)) + assert state_vec.shape == (4,) + assert state_fidelity( + state_vec, [0.7071067811865475, 0.0, 0.0, 0.7071067811865475] + ) == pytest.approx(1) -- Gitee From 544fcff3956df95d306930c8ad13936b32d77310 Mon Sep 17 00:00:00 2001 From: Xiang Fu Date: Wed, 17 Apr 2024 16:23:55 +0800 Subject: [PATCH 06/13] =?UTF-8?q?=F0=9F=90=9E=20fix(qualesim):=20fix=20qua?= =?UTF-8?q?lesim=20import=20error?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/quingo/backend/qualesim_quantumsim.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/quingo/backend/qualesim_quantumsim.py b/src/quingo/backend/qualesim_quantumsim.py index ae554e3..4fc5128 100644 --- a/src/quingo/backend/qualesim_quantumsim.py +++ b/src/quingo/backend/qualesim_quantumsim.py @@ -2,7 +2,8 @@ from quingo.utils import ensure_path from .backend_hub import BackendType from .if_backend import If_backend from quingo.core.exe_config import ExeConfig, ExeMode -from qualesim.plugin import Simulator, Loglevel +from qualesim.plugin import Loglevel +from qualesim.host import Simulator class QuaLeSim_quantumsim(If_backend): -- Gitee From cc4e635041104e28ecb4eddf7671d55aa2e461be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E5=AE=9A=E4=B8=9C?= <3081545786@qq.com> Date: Tue, 23 Apr 2024 11:24:10 +0800 Subject: [PATCH 07/13] =?UTF-8?q?=E2=9C=A8=20feat:=20add=20qualesim-tequil?= =?UTF-8?q?a=20backend,=20passed=20all=20unittest?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- setup.cfg | 7 +- src/quingo/backend/backend_hub.py | 14 +-- src/quingo/backend/qualesim_tequila.py | 128 ++++++++++++------------- unittest/test_backends.py | 37 ++++--- 4 files changed, 88 insertions(+), 98 deletions(-) diff --git a/setup.cfg b/setup.cfg index f2849ce..1ecbf6f 100644 --- a/setup.cfg +++ b/setup.cfg @@ -31,9 +31,10 @@ install_requires = tqdm pyezq qualesim - qualesim-quiets - qualesim-quantumsim - qualesim-qcis + qualesim-quiets >= 1.0.8 + qualesim-quantumsim >= 1.0.3 + qualesim-qcis >= 1.0.1 + qualesim-tequila >= 1.0.2 [options.packages.find] where = src \ No newline at end of file diff --git a/src/quingo/backend/backend_hub.py b/src/quingo/backend/backend_hub.py index 234cb77..1dcea64 100755 --- a/src/quingo/backend/backend_hub.py +++ b/src/quingo/backend/backend_hub.py @@ -9,7 +9,7 @@ class BackendType(enum.Enum): SYMQC = enum.auto() QUANTIFY = enum.auto() XIAOHONG = enum.auto() - # QUALESIM_TEQUILA = enum.auto() + QUALESIM_TEQUILA = enum.auto() QUALESIM_QUANTUMSIM = enum.auto() @@ -58,12 +58,12 @@ class Backend_hub: False, Qisa.QCIS, ), - # BackendType.QUALESIM_TEQUILA: ( - # "QuaLeSim_tequila", - # "qualesim_tequila", - # True, - # Qisa.QCIS, - # ), + BackendType.QUALESIM_TEQUILA: ( + "QuaLeSim_tequila", + "qualesim_tequila", + True, + Qisa.QCIS, + ), BackendType.QUALESIM_QUANTUMSIM: ( "QuaLeSim_quantumsim", "qualesim_quantumsim", diff --git a/src/quingo/backend/qualesim_tequila.py b/src/quingo/backend/qualesim_tequila.py index 2dce574..06bb647 100644 --- a/src/quingo/backend/qualesim_tequila.py +++ b/src/quingo/backend/qualesim_tequila.py @@ -1,78 +1,68 @@ -# from .backend_hub import BackendType -# from .if_backend import If_backend -# from quingo.core.exe_config import * -# from quingo.core.utils import * -# from dqcsim.plugin import * -# from dqcsim.host import * +from .backend_hub import BackendType +from .if_backend import If_backend +from quingo.core.exe_config import * +from quingo.core.utils import * +from qualesim.plugin import * +from qualesim.host import * -# logger = get_logger((__name__).split(".")[-1]) +logger = get_logger((__name__).split(".")[-1]) -# def bitwise_reverse_sort(lst, k): -# sorted_lst = [] -# for i in range(len(lst)): -# sorted_lst.append(lst[int("0b" + bin(i)[2:].zfill(k)[::-1], 2)]) -# return sorted_lst +class QuaLeSim_tequila(If_backend): + """A functional QCIS simulation backend using PyQCISim and Tequila.""" + def __init__(self): + super().__init__(BackendType.QUALESIM_TEQUILA) + self.sim = Simulator(stderr_verbosity=Loglevel.OFF) + self.sim.with_backend("tequila", verbosity=Loglevel.OFF) + self.res = None -# class QuaLeSim_tequila(If_backend): -# """A functional QCIS simulation backend using PyQCISim and Tequila.""" + def upload_program(self, prog_fn): + prog_fn = ensure_path(prog_fn) + if str(prog_fn).endswith(".qcis") or str(prog_fn).endswith(".qi"): + self.sim.with_frontend(str(prog_fn), verbosity=Loglevel.OFF) + else: + raise TypeError( + "The tequila simulator can only accept QCIS or QUIET-S instructions." + ) -# def __init__(self): -# super().__init__(BackendType.QUALESIM_TEQUILA) -# self.sim = Simulator(stderr_verbosity=Loglevel.OFF) -# self.sim.with_backend("tequila", verbosity=Loglevel.OFF) -# self.res = None + def execute(self, exe_config: ExeConfig): + if exe_config.mode == ExeMode.SimFinalResult: + measure_mod = "one_shot" + try: + self.sim.simulate() + res = self.sim.run( + measure_mod=measure_mod, num_shots=exe_config.num_shots + ) + self.sim.stop() + final_state = res["res"] + final_state["quantum"] = tuple(final_state["quantum"]) + return final_state["quantum"] + except: + raise ValueError( + "Here is some wrong with ({}) for QUALESIM_TEQUILA.".format( + exe_config.mode + ) + ) -# def upload_program(self, prog_fn): -# prog_fn = ensure_path(prog_fn) -# if str(prog_fn).endswith(".qcis") or str(prog_fn).endswith(".qi"): -# self.sim.with_frontend(str(prog_fn), verbosity=Loglevel.OFF) -# else: -# raise TypeError( -# "The tequila simulator can only accept QCIS or QUIET-S instructions." -# ) + if exe_config.mode == ExeMode.SimStateVector: + measure_mod = "state_vector" + try: + self.sim.simulate() + res = self.sim.run(measure_mod=measure_mod) + self.sim.stop() -# def execute(self, exe_config: ExeConfig): -# if exe_config.mode == ExeMode.SimFinalResult: -# measure_mod = "one_shot" -# try: -# self.sim.simulate() -# res = self.sim.run( -# measure_mod=measure_mod, num_shots=exe_config.num_shots -# ) -# self.sim.stop() -# final_state = res["res"] -# final_state["quantum"] = tuple(final_state["quantum"]) -# return final_state["quantum"] -# except: -# raise ValueError( -# "Here is some wrong with ({}) for QUALESIM_TEQUILA.".format( -# exe_config.mode -# ) -# ) + final_state = eval(res["res"]) + return final_state + except: + raise ValueError( + "Here is some wrong with ({}) for QUALESIM_TEQUILA.".format( + exe_config.mode + ) + ) -# if exe_config.mode == ExeMode.SimStateVector: -# measure_mod = "state_vector" -# try: -# self.sim.simulate() -# res = self.sim.run(measure_mod=measure_mod) -# self.sim.stop() -# final_state = eval(res["res"]) -# qu = bitwise_reverse_sort( -# final_state["quantum"][1], len(final_state["quantum"][0]) -# ) -# final_state["quantum"] = (final_state["quantum"][0], qu) -# return final_state -# except: -# raise ValueError( -# "Here is some wrong with ({}) for QUALESIM_TEQUILA.".format( -# exe_config.mode -# ) -# ) - -# raise ValueError( -# "Unsupported execution mode ({}) for QUALESIM_TEQUILA.".format( -# exe_config.mode -# ) -# ) + raise ValueError( + "Unsupported execution mode ({}) for QUALESIM_TEQUILA.".format( + exe_config.mode + ) + ) diff --git a/unittest/test_backends.py b/unittest/test_backends.py index 25ae9ca..76bc182 100644 --- a/unittest/test_backends.py +++ b/unittest/test_backends.py @@ -1,6 +1,8 @@ from quingo.backend.pyqcisim_tequila import PyQCISim_tequila from quingo.backend.pyqcisim_quantumsim import PyQCISim_quantumsim from quingo.backend.qualesim_quantumsim import QuaLeSim_quantumsim +from quingo.backend.qualesim_tequila import QuaLeSim_tequila + from quingo.backend.symqc import IfSymQC from quingo.backend.backend_hub import BackendType, Backend_hub from quingo.backend.qisa import Qisa @@ -17,11 +19,11 @@ quiet_fn = cur_dir / "test_qcis" / "bell.qi" quiet_fn2 = cur_dir / "test_qcis" / "bell_copy.qi" -def dist(a, b): - if isinstance(a, complex) and isinstance(b, complex): - return (a.real - b.real) ** 2 + (a.imag - b.imag) ** 2 - else: - return (a.evalf() - b.evalf()) ** 2 +# def dist(a, b): +# if isinstance(a, complex) and isinstance(b, complex): +# return (a.real - b.real) ** 2 + (a.imag - b.imag) ** 2 +# else: +# return (a.evalf() - b.evalf()) ** 2 # progress: 2023-10-09 @@ -35,7 +37,7 @@ class Test_backends: assert sim.is_simulator() == is_sim # QuaLeSim_tequila and QuaLeSim_quantumsim default Qisa type is QCIS - # single(QuaLeSim_tequila, BackendType.QUALESIM_TEQUILA, Qisa.QCIS, True) + single(QuaLeSim_tequila, BackendType.QUALESIM_TEQUILA, Qisa.QCIS, True) single(QuaLeSim_quantumsim, BackendType.QUALESIM_QUANTUMSIM, Qisa.QCIS, True) single(PyQCISim_tequila, BackendType.TEQUILA, Qisa.QCIS, True) single(PyQCISim_quantumsim, BackendType.QUANTUM_SIM, Qisa.QCIS, True) @@ -49,8 +51,8 @@ class Test_backends: except Exception as e: assert False, "upload_program failed: {}".format(e) - # single(QuaLeSim_tequila, qcis_fn) - # single(QuaLeSim_tequila, quiet_fn) + single(QuaLeSim_tequila, qcis_fn) + single(QuaLeSim_tequila, quiet_fn) single(QuaLeSim_quantumsim, qcis_fn) single(QuaLeSim_quantumsim, quiet_fn) single(PyQCISim_tequila, qcis_fn) @@ -63,14 +65,13 @@ class Test_backends: sim.upload_program(qasm_fn) exe_config = ExeConfig(ExeMode.SimFinalResult, 10) res = sim.execute(exe_config) - print(res) - # assert len(res) == 2 - # assert res[0] == ["Q1", "Q2"] - # assert all(v in [[0, 0], [1, 1]] for v in res[1]) + assert len(res) == 2 + assert res[0] == ["Q1", "Q2"] + assert all(v in [[0, 0], [1, 1]] for v in res[1]) - # single(QuaLeSim_tequila, qcis_fn) + single(QuaLeSim_tequila, qcis_fn) single(QuaLeSim_quantumsim, qcis_fn) - # single(QuaLeSim_tequila, quiet_fn) + single(QuaLeSim_tequila, quiet_fn) single(QuaLeSim_quantumsim, quiet_fn) single(PyQCISim_tequila, qcis_fn) single(PyQCISim_quantumsim, qcis_fn) @@ -124,13 +125,11 @@ class Test_backends: res = sim.execute(exe_config) a = res["quantum"][1][0] b = res["quantum"][1][3] - assert res["quantum"][0] == ["Q1", "Q2"] - assert dist(a, b) <= 0.01 - # single(BackendType.QUALESIM_TEQUILA, quiet_fn2) + single(BackendType.QUALESIM_TEQUILA, quiet_fn2) single(BackendType.QUALESIM_QUANTUMSIM, quiet_fn2) - # single(BackendType.QUALESIM_TEQUILA, qcis_fn) + single(BackendType.QUALESIM_TEQUILA, qcis_fn) single(BackendType.QUALESIM_QUANTUMSIM, qcis_fn) single(BackendType.QUANTUM_SIM, qcis_fn2) single(BackendType.SYMQC, qcis_fn2) @@ -163,7 +162,7 @@ class Test_backends: t1.start() t2.start() - # single(BackendType.QUALESIM_TEQUILA) + single(BackendType.QUALESIM_TEQUILA) single(BackendType.QUALESIM_QUANTUMSIM) single(BackendType.QUANTUM_SIM) single(BackendType.TEQUILA) -- Gitee From fb4f114ec5b27ce1075d34aa8036e5b89e669a29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E5=AE=9A=E4=B8=9C?= <3081545786@qq.com> Date: Tue, 23 Apr 2024 11:29:02 +0800 Subject: [PATCH 08/13] =?UTF-8?q?=F0=9F=94=A7=20build:=20upgrade=20version?= =?UTF-8?q?=20number=20of=20qualesim?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 1ecbf6f..11dfabe 100644 --- a/setup.cfg +++ b/setup.cfg @@ -30,7 +30,7 @@ install_requires = requests tqdm pyezq - qualesim + qualesim >= 1.0.0 qualesim-quiets >= 1.0.8 qualesim-quantumsim >= 1.0.3 qualesim-qcis >= 1.0.1 -- Gitee From b26b6117b0bcdcb22cd8942de9ae7020fa3089ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E5=AE=9A=E4=B8=9C?= <3081545786@qq.com> Date: Tue, 23 Apr 2024 16:40:28 +0800 Subject: [PATCH 09/13] =?UTF-8?q?=F0=9F=93=83=20docs:=20update=20docs=20Re?= =?UTF-8?q?adme=20and=20fix=20qisa=5Ftype=20in=20quingo=5Ftask?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 45 +++++++++++++++----------------- README_ZH.md | 47 +++++++++++++++------------------- src/quingo/core/quingo_task.py | 2 +- 3 files changed, 42 insertions(+), 52 deletions(-) diff --git a/README.md b/README.md index 1a0ceb0..46b2df6 100755 --- a/README.md +++ b/README.md @@ -14,19 +14,12 @@ pip install -e . ```sh # for simulators used: +# The Tequila backend is not yet open source and needs to be installed separately. git clone https://gitee.com/hpcl_quanta/tequila.git -git checkout xbackend -pip install -e . - -git clone https://gitee.com/quingo/pyqcisim.git -git checkout bug-fix -pip install -e . - -git clone https://gitee.com/quingo/SymQC.git pip install -e . ``` -Upon success, it will automatically install the Quingo runtime system (this package), the PyQCAS simulator and the PyQCISim simulator. +Upon success, it will automatically install the Quingo runtime system (this package), the SymQC simulator, the PyQCISim simulator and the QuaLeSim simulator. ### Install the Quingo compiler @@ -61,22 +54,24 @@ For different simulation backend, please refer to `src/examples/sim_backend`, wh For different simulation modes, please refer to `src/examples/sim_exemode`, which displays the output of two different simulation results currently available. ## APIs of the Quingo runtime system -The `Quingo_interface` class expose the following methods: - - `set_log_level()`: `` can be one of `DEBUG`, `INFO`, `WARNING`, `ERROR`, or `CRITICAL`. - - `connect_backend()`: `` currently can be `'pyqcas_quantumsim'` or `'pyqcisim_quantumsim'`. -- `get_backend_name()`: return the name of the backend that is being used. An empty string will be returned if no backend has been set. -- `get_last_qasm()`: get the qasm code generated by the last execution. -- `config_execution(, )`: - - Configure the execution mode to `'one_shot'` or `'state_vector'`. - - When the execution mode is `'one_shot'`, the number of times to run the uploaded quantum circuit can be configured using the parameter `num_shots` at the same time. -- `call_quingo(, , *args)`: - - the main entry to call Quingo operation. - - `` : the name of the Qingo file which contains the quantum function called by the host program. - - `` : the name of the quantum function - - ``: a variable length of parameters used to call the Quingo operation in the form `qg_func_name()`. - - `read_result()`: read the computation result from the quantum kernel. - - For eQASM-based backend, the result is a binary block which encodes the quantum computation result. - - For QCIS-based backend, the result format is defined by PyQCISim. Please refer to the docstring of `quingo.if_backend.non_arch_backend.pyqcisim_quantumsim.PyQCISim_quantumsim::execute()` +1. `class Quingo_task`: + - 输入: + - `called_qu_fn`: `Path`,qu文件路径。 + - `called_func`: `str`,调用 quingo 函数名。 + - `debug_mode`(optional): `True` or `False`。 + - `qisa`(optional): 前端指令集类型。 + - `backend`(optional): 后端模拟器类型。 +2. `function compile()`: + - 输入: + - `Quingo_task`: 待编译 qu 任务 + - `params`: `Quingo_task` 中调用函数 `called_func` 所需参数 + - 输出:`qasm_fn`:输出对应指令集文件(.qcis / .qi) +3. `function execute()`: + - 输入: + - `qasm_fn`: `Path`,对应指令集文件(.qcis / .qi) + - `be_type`: `BackendType`,模拟器后端类型 + - `exe_config`: 执行模式,`ExeMode.SimShots`、`ExeMode.SimFinalResult`、`ExeMode.SimStateVector` + - 输出:`sim_result`:具体输出格式详见`src/quingo/backend/quingo_result_format_spec.md` ## Quingo programming tutorial At present, Qingguo runtime system has included sample programs such as `Bell_state`, `GHZ`, `VQE`, etc. Details can be found [here](https://gitee.com/quingo/quingo-runtime/tree/master/src/examples). \ No newline at end of file diff --git a/README_ZH.md b/README_ZH.md index 5e92c7b..d7f2367 100755 --- a/README_ZH.md +++ b/README_ZH.md @@ -8,22 +8,15 @@ ### 安装运行时系统以及模拟器 -依次执行以下命令便可以安装青果运行时系统、PyQCAS模拟器以及PyQCISim模拟器。 +依次执行以下命令便可以安装青果运行时系统、`SymQC` 模拟器、`PyQCISim` 模拟器以及 `QuaLeSim` 模拟器。 ```sh pip install -e . ``` ```sh # for simulators used: +# Tequila 后端尚未开源,需要单独安装。 git clone https://gitee.com/hpcl_quanta/tequila.git -git checkout xbackend -pip install -e . - -git clone https://gitee.com/quingo/pyqcisim.git -git checkout bug-fix -pip install -e . - -git clone https://gitee.com/quingo/SymQC.git pip install -e . ``` @@ -58,25 +51,27 @@ sim res: (['Q1', 'Q2'], [[0, 0], [0, 0], [1, 1], [1, 1], [0, 0], [0, 0], [0, 0] ``` 针对不同的模拟后端,详见`src/examples/sim_backend`,其中展示了目前稳定运行的SymQC、QuantumSim何Tequila后端的使用。 -针对不同的模拟模式,详见`src/examples/sim_exemode`,展示了对于目前的两种不同的模拟结果的输出。 +针对不同模式的输出格式,详见`src/quingo/backend/quingo_result_format_spec.md` ## 青果运行时系统提供的API -`Quingo_interface`类提供了以下方法: - - `set_log_level()`: 该方法中``的值可以是`DEBUG`, `INFO`, `WARNING`, `ERROR`, `CRITICAL`中的任意一个。 - - `connect_backend()`: 该方法中``的值目前可以是`'pyqcas_quantumsim'`或者`'pyqcisim_quantumsim'`。 -- `get_backend_name()`方法返回正在使用的后端名称。如果没有设置后端,将返回一个空字符串。 -- `get_last_qasm()`用来获取上次执行生成的qasm指令代码。 -- `config_execution(, )`: - - `config_execution`能够将执行模式配置为`'one_shot'`或`'state_vector'`. - - 当执行模式为`'one_shot'`时,可以同时使用参数`num_shots`来配置量子线路的运行次数。 -- `call_quingo(, , *args)`: - - `call_quingo`方法是调用Quingo操作的主要入口。 - - ``中的值为青果文件的名称,该青果文件中包含被宿主程序调用的量子操作。 - - ``中的值为量子操作的名称。 - - ``中的值为可变长度的参数,这些参数用来以 `qg_func_name()` 形式来调用青果操作。 -- `read_result()`方法负责从量子内核中读取计算结果。 - - 对于能够执行eQASM指令的后端,结果是对量子计算结果进行编码的二进制块。 - - 对于能够执行QCIS指令的后端,结果的格式由PyQCISim进行定义。详情请参考`quingo.if_backend.non_arch_backend.pyqcisim_quantumsim.PyQCISim_quantumsim::execute()`中的文档描述。 +1. `Quingo_task`类: + - 输入: + - `called_qu_fn`: `Path`,qu文件路径。 + - `called_func`: `str`,调用 quingo 函数名。 + - `debug_mode`(optional): `True` or `False`。 + - `qisa`(optional): 前端指令集类型。 + - `backend`(optional): 后端模拟器类型。 +2. `compile`: + - 输入: + - `Quingo_task`: 待编译 qu 任务 + - `params`: `Quingo_task` 中调用函数 `called_func` 所需参数 + - 输出:`qasm_fn`:输出对应指令集文件(.qcis / .qi) +3. `execute`: + - 输入: + - `qasm_fn`: `Path`,对应指令集文件(.qcis / .qi) + - `be_type`: `BackendType`,模拟器后端类型 + - `exe_config`: 执行模式,`ExeMode.SimShots`、`ExeMode.SimFinalResult`、`ExeMode.SimStateVector` + - 输出:`sim_result`:具体输出格式详见`src/quingo/backend/quingo_result_format_spec.md` ## 青果示例程序 目前青果运行时系统中已经包含了`Bell_state`、`GHZ`、`VQE`等示例程序,详情可见[此处](https://gitee.com/quingo/quingo-runtime/tree/master/src/examples)。 \ No newline at end of file diff --git a/src/quingo/core/quingo_task.py b/src/quingo/core/quingo_task.py index 01c9cc0..c662ae4 100644 --- a/src/quingo/core/quingo_task.py +++ b/src/quingo/core/quingo_task.py @@ -108,7 +108,7 @@ class Quingo_task: BackendType.SYMQC, BackendType.XIAOHONG, BackendType.QUALESIM_QUANTUMSIM, - # BackendType.QUALESIM_TEQUILA, + BackendType.QUALESIM_TEQUILA, ]: return Qisa.QCIS -- Gitee From 7797f920a53bb501c9cd6aa0d1bc28e6f750d3f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E5=AE=9A=E4=B8=9C?= <3081545786@qq.com> Date: Wed, 24 Apr 2024 10:02:29 +0800 Subject: [PATCH 10/13] =?UTF-8?q?=F0=9F=90=B3=20chore:=20update=20install?= =?UTF-8?q?=5Frequires's=20version=20number.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- setup.cfg | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/setup.cfg b/setup.cfg index 019e220..98cd1e7 100644 --- a/setup.cfg +++ b/setup.cfg @@ -22,13 +22,13 @@ packages =find: python_requires = >=3.7 install_requires = numpy - pyqcisim - symqc + pyqcisim >= 1.3.1 + symqc >= 1.1.1 colorama termcolor requests tqdm - qualesim >= 1.0.0 + qualesim >= 1.0.2 qualesim-tequila >= 1.0.2 pyquiet >= 0.0.4 -- Gitee From 09b8b8781c441f699ea6118bec72a4cc0ffa0355 Mon Sep 17 00:00:00 2001 From: Xiang Fu Date: Wed, 24 Apr 2024 11:52:12 +0800 Subject: [PATCH 11/13] update version number to 0.3.1 --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 98cd1e7..cb1dc12 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = quingo -version = 0.3.0 +version = 0.3.1 author = Xiang Fu author_email = gtaifu@gmail.com use_2to3 = False -- Gitee From 5588df989caa1b0985fa36132cb2421e3b2b9851 Mon Sep 17 00:00:00 2001 From: Xiang Fu Date: Sun, 28 Apr 2024 11:33:31 +0800 Subject: [PATCH 12/13] =?UTF-8?q?=E2=9C=A8=20feat(visualization):=20add=20?= =?UTF-8?q?converting=20qcis=20to=20qiskit=20qc=20and=20circ=20drawing?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/quingo/lib/qiskit_tools.py | 33 ++++++++++++ tests/qiskit_tools_test.ipynb | 93 ++++++++++++++++++++++++++++++++++ 2 files changed, 126 insertions(+) create mode 100644 src/quingo/lib/qiskit_tools.py create mode 100644 tests/qiskit_tools_test.ipynb diff --git a/src/quingo/lib/qiskit_tools.py b/src/quingo/lib/qiskit_tools.py new file mode 100644 index 0000000..1176483 --- /dev/null +++ b/src/quingo/lib/qiskit_tools.py @@ -0,0 +1,33 @@ +"""Visualization functions for quantum circuits. + +Note, this module requires qiskit to be installed. +""" + +from qiskit import QuantumCircuit +from pathlib import Path +from pyqcisim.qcis_to_openqasm import qcis_file_2_qasm_file + + +def qcis_2_qiskit_qc(qcis_fn: Path): + """Convert a QCIS file to a qiskit QuantumCircuit object.""" + qasm_fn = qcis_fn.with_suffix(".qasm") + qasm_str = qcis_file_2_qasm_file(qcis_fn, qasm_fn) + return QuantumCircuit.from_qasm_file(str(qasm_fn)) + + +def draw_circ(qcis_fn: Path, output="mpl"): + """Draw the quantum circuit using qiskit. + Use the output parameter to choose the drawing format: + + **text**: ASCII art TextDrawing that can be printed in the console. + + **mpl**: images with color rendered purely in Python using matplotlib. + + **latex**: high-quality images compiled via latex. + + **latex_source**: raw uncompiled latex output. + """ + qasm_fn = qcis_fn.with_suffix(".qasm") + qasm_str = qcis_file_2_qasm_file(qcis_fn, qasm_fn) + qc = QuantumCircuit.from_qasm_file(str(qasm_fn)) + return qc.draw(output=output) diff --git a/tests/qiskit_tools_test.ipynb b/tests/qiskit_tools_test.ipynb new file mode 100644 index 0000000..1911415 --- /dev/null +++ b/tests/qiskit_tools_test.ipynb @@ -0,0 +1,93 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "from quingo.lib.qiskit_tools import draw_circ, qcis_2_qiskit_qc\n", + "from pathlib import Path" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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7udwoco9baYmwaQMiPDNu4+K1FKIi18Y0Nl+HveqHXCkCTeMjAyFewZAegroeSBiAoW4+I24KJg2BL4stD8P87ATN5VrHQGZ3ex/osM9V6OIuynExa8EBNiHQlKT4NtzsD/f/jSeghIotkLN2aMRofYx76R4ew++R3udQihmUoiL32oXDUN61p122WYP+kANlYifUIhLi6LetvgbfaRFRAymEBcRMZhCXETEYApxERGD6cCmiPikyMhIrFarW9pauGQVZeUVxERFMuvxBxqc1hSOnk3QHBTiIuKTAgIC3Pbg4dCwcEIvXSY0LLy2TUfTTKThFBERgynERUQMphAXETGYQlxExGAKcRERgynERUQMphAXETGYQlxExGAKcRERgynERUQMphAXETGYQlxExGAKcRERgynERUQMphAXETGYQlxExGAKcRERgynERUQMphAXETGYQlxExGAKcRERgynERUQMphD3AQsXLiQjI4O4uDhiY2MZPHgwGzZs8HZZIte0fv16+vbtS1hYGCkpKbzyyiveLqlZbdmyhXHjxtGpUycCAgJ48cUXvVKHQtwHbN68mR/96Ed88sknfP7552RmZjJmzBi2bdvm7dJEHMrJyWHcuHGMHDmS3NxcXnjhBebMmcPrr7/u7dKajdVqpWfPnrz88sskJCR4rY5gr21Zan300Ud1Xr/88sts2LCBNWvWcNttt3mpKpGGvfLKKwwcOJD58+cD0KNHD7788kteeuklpk2b5uXqmseoUaMYNWoUALNnz/ZaHQpxH2Sz2SgrKyMqKsrbpYhhLly8xDeFp+pNr7p8ufbn0a8L6r2+0o1t42gdfe3P3rZt23jkkUfqTBsxYgSLFi2ioKCApKSkpryNJvlX4SkqL16qM83R+23o7yAiLJTk9jc0U7VNpxD3QfPmzePMmTM89thj3i5FDBMSEszWz/dxLK/Q4fyK85X87k/rG3wdG9OKmT+697rbKSoqqjeEUPO6qKjIqyFecvYcq/662eG8q9+vo2k/HD+MZI9W6F4aE/cxixcvZt68ebz33nte/Y8gZgoMCODeUXcSER7m0voTR91JeFiom6tqXn17dqXPLV1cWrd/andSb+7s5oo8SyHuQxYtWsSsWbP48MMPGTp0qLfLEUO1jo5i/DDnj6UMHtibmzq1b9SyiYmJWCyWOtNOnTpVO8/bxt81mJhWkU6tExvTiruHZnqoIs9RiPuI559/nrlz57J+/XoFuDRZWs+upPW4qdHL39g2juG3D2z08rfddhsbN26sM23Dhg106tTJJ/YgIyPCuXfUnY1ePgC4b7SZeyEKcR8wc+ZMFi5cyDvvvMPNN9+MxWLBYrFw9uxZb5cmBht312BiWl3/4HhQYCD3jckiJLjxh8h++tOf8vnnn/Pcc89x+PBhfv/73/Ob3/yGZ555piklu1X3zklk9O/VqGUHD+xDl46N2wupYbVayc3NJTc3l4sXL2KxWMjNzeX48eOulOuygOrq6upm3aLUExAQ4HD6lClTeOutt5q3GPErx74uYPlVB/KuNvz2gWRl9HO67XXr1jFnzhwOHz5MQkICM2bM4Gc/+5mrpXrExUtV/Oat9/m2pOEO0Y1t43hyygSnvsQAPv30U7KysupNv+OOO/j000+dLdVlCnHDfJ1fRFJCO0JCdGKRNM6HH2/jn7u/dDivU4cbefwHYwkM9N+d8vyi/+W37/wFm4OoCwoMZPqUCbS/oY0XKnMP//2X80PnrBUs/9N6Xl66irNlVm+XI4YYccd/0S4+tt700JBg7hud5dcBDpCceANDMvs7nDfsOwOMDnBQiBvls537qKq6TFxMNDHXuRhDpEZoSDD3j8kiMLDusN2Y72bSJi7GS1U1r6yMfiQntqszLSUpgdsH9fFSRe6jEL/C5cuXeeedd7jrrrto164dYWFhdOzYkREjRrBs2TIu//sKL284Z61gR+5BAIYOTm9wHF3EkaTEdnw3M732dY+uHRnY52YvVtS8goJqDt4GARAaGsLE0Xf6xV6I+e/ATcrKyhg2bBiTJ0/mb3/7G6GhoaSlpWGz2di0aROPPvoo586d81p9Nb3wju1vpFtKB6/VIea6M6MvyYk3EBURzj0jbm9xHYF28bGMyroVgLFDMmgT6x97ITqw+W8TJ06svUry7bffrnPU+dSpUyxfvpwZM2a4dD+T3/x+Dees512uzWazYa2wrx8ZHkawk0fRRWrYqm3YbDaCg1ruZ+jipUuEhoR4u4x6oltF8JMp9zi9nkIc2L17NwMGDCA4OJi9e/eSmprq1vbn/c8fKbOWu7VNEfEvMa2imDN9ktPrtdyv4yt88MEHAIwePdrtAQ72b1hXqRcu0jK4mhNKBODgQfsBw4yMDI+078ouUo21f9/OP3L207H9jTzxw7tb3DimiFybQhz7QU2A1q1be6R9V8fEr+yFF5ecYf7iFe4uTUR8hKtj4gpxICbGfpTaU/cqOWc93+Qx8YrKC8AF9xQkIn5DIQ706tWLNWvWsH37do+078pYl8bCRVoWV8fEdXYKsHfvXvr3709ISAi5ubn07NnT2yVpLFxEGkUX+wD9+vXjvvvu49KlS4wcOZLPPvuszvxTp04xf/58ysub5zRBXZ0pIo2lnvi/lZWVMW7cuNpbSHbo0IH27dtTVFREYWEh1dXVlJaWEhsb6/Fa1AsXkcZST/zfYmJi+Pjjj1m+fDl33nknFRUV7Nu3j8DAQIYPH87y5cuJjo5ullpaRUUQHhaqXriIXJd64j6q8sJFwkJDFOIick0KcRERg2k4RUTEYApxERGDKcRFRAymEBcRMZhCXETEYApxERGDKcRFRAymEBcRMZhCXETEYApxERGDKcRFRAymEBcRMZhCXETEYApxERGDKcRFRAymEBcRMZhCXETEYApxERGDKcRFRAymEBcRMZhCXETEYApxERGDKcRFRAymEBcRMZhCXETEYApxERGDKcRFRAymEBcRMZhCXETEYApxERGDKcRFRAymEBcRMZhCXETEYApxERGDKcRFRAymEBcRMZhCXETEYApxERGDKcRFRAz2/wHoKkgHdFVPHgAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "qcis_fn = Path('/tmp/quingo-9mp_zcgv/main_kernel_bell_state.qcis')\n", + "draw_circ(qcis_fn, output='mpl')" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "qc = qcis_2_qiskit_qc(qcis_fn)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "3" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "qc.depth()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "quingo", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.17" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} -- Gitee From d3f25b2bed83d56e03549982b011106319511a8d Mon Sep 17 00:00:00 2001 From: Xiang Fu Date: Mon, 29 Apr 2024 21:23:50 +0800 Subject: [PATCH 13/13] =?UTF-8?q?=F0=9F=94=A7=20build:=20update=20version?= =?UTF-8?q?=20number=20to=200.3.2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index cb1dc12..5bb5b89 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = quingo -version = 0.3.1 +version = 0.3.2 author = Xiang Fu author_email = gtaifu@gmail.com use_2to3 = False -- Gitee