From 3b734bd36f6fe1f8269f481a81295a06ca5efb37 Mon Sep 17 00:00:00 2001 From: Xiang Fu Date: Sun, 27 Apr 2025 14:13:27 +0800 Subject: [PATCH 1/3] add tianyan qcloud platform --- examples/xiaohong/host.py | 6 +- src/quingo/backend/backend_hub.py | 7 ++ src/quingo/backend/tianyan.py | 112 +++++++++++++++++++++++++++++ src/quingo/backend/xiaohong.py | 9 ++- src/quingo/core/exe_config.py | 8 +-- unittest/backends/test_backends.py | 17 +++-- unittest/backends/test_tianyan.py | 26 +++++++ unittest/test_qcis/bell_cz.qcis | 6 ++ 8 files changed, 175 insertions(+), 16 deletions(-) create mode 100644 src/quingo/backend/tianyan.py create mode 100644 unittest/backends/test_tianyan.py create mode 100644 unittest/test_qcis/bell_cz.qcis diff --git a/examples/xiaohong/host.py b/examples/xiaohong/host.py index ff22041..d14c2e0 100644 --- a/examples/xiaohong/host.py +++ b/examples/xiaohong/host.py @@ -1,6 +1,6 @@ -from quingo import * from pathlib import Path +from quingo import * qu_file = Path(__file__).parent / "kernel.qu" @@ -10,8 +10,8 @@ def routine(circ_name, num_shots=1): cfg = ExeConfig( ExeMode.RealMachine, num_shots, - xh_login_key="7e6999bab11453428b8ded1fac00b3ea", - xh_machine_name="Transpose", + qcloud_platform_login_key="7e6999bab11453428b8ded1fac00b3ea", + qcloud_machine_name="Transpose", ) qasm_fn = compile(task, params=(), config_file="", target="qcloud_sh") res = execute(qasm_fn, BackendType.XIAOHONG, cfg) diff --git a/src/quingo/backend/backend_hub.py b/src/quingo/backend/backend_hub.py index d1fb375..87fe27f 100755 --- a/src/quingo/backend/backend_hub.py +++ b/src/quingo/backend/backend_hub.py @@ -10,6 +10,7 @@ class BackendType(enum.Enum): SYMQC = enum.auto() QUANTIFY = enum.auto() XIAOHONG = enum.auto() + TIANYAN = enum.auto() QUALESIM_TEQUILA = enum.auto() QUALESIM_QUANTUMSIM = enum.auto() QOS = enum.auto() @@ -49,6 +50,12 @@ class Backend_hub: False, Qisa.QCIS, ), + BackendType.TIANYAN: ( + "ZDXLZ_Tianyan", + "tianyan", + False, + Qisa.QCIS, + ), BackendType.QUALESIM_TEQUILA: ( "QuaLeSim_tequila", "qualesim", diff --git a/src/quingo/backend/tianyan.py b/src/quingo/backend/tianyan.py new file mode 100644 index 0000000..e97bfe1 --- /dev/null +++ b/src/quingo/backend/tianyan.py @@ -0,0 +1,112 @@ +from datetime import datetime + +from cqlib import TianYanPlatform + +from quingo.core.exe_config import ExeConfig, ExeMode +from quingo.utils import ensure_path + +from .backend_hub import BackendType +from .if_backend import If_backend + + +class ZDXLZ_Tianyan(If_backend): + def __init__(self): + super().__init__(BackendType.TIANYAN) + self.ty_platform = None + self.qcis_circuit = None + + def upload_program(self, prog_fn): + """ + Upload assembly or binary program to the simulator. + + Args: + prog_fn: the name of the assembly or binary file. + """ + prog_fn = ensure_path(prog_fn) + lines = [] + with prog_fn.open("r") as f: + lines = f.readlines() + + if len(lines) == 0: + raise ValueError("The program file is empty.") + + trimed_lines = [] + for line in lines: + trimed_lines.append(" ".join(line.split())) + + self.qcis_circuit = "\n".join( + [ + line.strip() + for line in trimed_lines + if line.strip() and not line.startswith("#") + ] + ) + # self.qcis_circuit = prog_fn.open("r").read() + + def upload_program_str(self, program: str): + """upload the program string to the simulator.""" + self.qcis_circuit = program + + 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. + - num_shots (int): the number of iterations performed in `one_shot` mode. + - xh_login_key (str): login key to connect XiaoHong + - xh_machine_name (str): name of machine name to execute qcis + """ + if not exe_config.mode == ExeMode.RealMachine: + raise ValueError( + f"Unsupported execution mode ({exe_config.mode}) for Tianyan." + ) + + # connect Tianyan + self.configure_platform( + exe_config.qcloud_platform_login_key, exe_config.qcloud_machine_name + ) + + # submit job + print(f"\n===================== Start execute: ===================== ") + + print("circuit:\n", self.qcis_circuit, sep="") + print( + "type of circuit:", + type(self.qcis_circuit), + " length:", + len(self.qcis_circuit), + ) + print("machine name:", exe_config.qcloud_machine_name) + print(f"num shots = {exe_config.num_shots}") + + print("") + + query_id = self.ty_platform.submit_job( + circuit=self.qcis_circuit, + exp_name=f'quingo_exp.{datetime.now().strftime("%Y%m%d%H%M%S")}', + num_shots=exe_config.num_shots, + ) + + # invalid query + if not query_id: + raise EnvironmentError("Fail to connect Tianyan!") + + # read result + result = self.ty_platform.query_experiment( + query_id=query_id, max_wait_time=3600, sleep_time=5 + ) + result = self.format_result(result) + return result + + def configure_platform(self, login_key, machine_name): + self.ty_platform = TianYanPlatform(login_key=login_key) + print(f"Set account successfully:") + print(f" login key = {login_key[0:5]}" + "*" * (len(login_key) - 5)) + self.ty_platform.set_machine(machine_name) + print(f" machine name = {machine_name}") + + def format_result(self, result): + print("result:", result) + # origin_result = result[0]["results"] + # return {"qubits": origin_result[0], "results": origin_result[1:]} diff --git a/src/quingo/backend/xiaohong.py b/src/quingo/backend/xiaohong.py index b0a4cf1..33dd627 100644 --- a/src/quingo/backend/xiaohong.py +++ b/src/quingo/backend/xiaohong.py @@ -1,8 +1,9 @@ +from quingo.core.exe_config import ExeConfig, ExeMode +from quingo.lib.pyezQ import Account 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 quingo.lib.pyezQ import Account class XiaoHong(If_backend): @@ -41,7 +42,9 @@ class XiaoHong(If_backend): ) # connect XiaoHong - self.set_account(exe_config.xh_login_key, exe_config.xh_machine_name) + self.set_account( + exe_config.qcloud_platform_login_key, exe_config.qcloud_machine_name + ) # submit job print(f"Start execute:") diff --git a/src/quingo/core/exe_config.py b/src/quingo/core/exe_config.py index 56c4e2d..e31477d 100644 --- a/src/quingo/core/exe_config.py +++ b/src/quingo/core/exe_config.py @@ -25,15 +25,15 @@ class ExeConfig: self, 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 + qcloud_platform_login_key: str = None, # use for connecting XIAOHONG + qcloud_machine_name: str = None, # use for connecting XIAOHONG qos_circuit_times: int = 100, # use for connecting QOS noise_config=None, ): self.mode = mode self.num_shots = num_shots - self.xh_login_key = xh_login_key - self.xh_machine_name = xh_machine_name + self.qcloud_platform_login_key = qcloud_platform_login_key + self.qcloud_machine_name = qcloud_machine_name self.qos_circuit_times = qos_circuit_times self.noise_config = noise_config diff --git a/unittest/backends/test_backends.py b/unittest/backends/test_backends.py index 522729b..2fe6ce1 100644 --- a/unittest/backends/test_backends.py +++ b/unittest/backends/test_backends.py @@ -1,14 +1,15 @@ -from quingo.backend.pyqcisim_tequila import PyQCISim_tequila +import threading +from pathlib import Path + +from quingo.backend.backend_hub import Backend_hub, BackendType from quingo.backend.pyqcisim_quantumsim import PyQCISim_quantumsim +from quingo.backend.pyqcisim_tequila import PyQCISim_tequila +from quingo.backend.qisa import Qisa from quingo.backend.qualesim import QuaLeSim_quantumsim, QuaLeSim_tequila from quingo.backend.symqc import IfSymQC -from quingo.backend.backend_hub import BackendType, Backend_hub -from quingo.backend.qisa import Qisa +from quingo.backend.tianyan import ZDXLZ_Tianyan 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" @@ -33,6 +34,7 @@ class Test_backends: single(PyQCISim_tequila, BackendType.TEQUILA, Qisa.QCIS, True) single(PyQCISim_quantumsim, BackendType.QUANTUM_SIM, Qisa.QCIS, True) single(IfSymQC, BackendType.SYMQC, Qisa.QCIS, True) + single(ZDXLZ_Tianyan, BackendType.TIANYAN, Qisa.QCIS, False) def test_upload_program(self): def single(BackendClass, qasm_fn): @@ -49,6 +51,7 @@ class Test_backends: single(PyQCISim_tequila, qcis_fn) single(PyQCISim_quantumsim, qcis_fn) single(IfSymQC, qcis_fn) + single(ZDXLZ_Tianyan, qcis_fn) def test_upload_program_str(self): def single(BackendClass, qasm): @@ -62,6 +65,7 @@ class Test_backends: single(PyQCISim_tequila, qasm_str) single(PyQCISim_quantumsim, qasm_str) single(IfSymQC, qasm_str) + single(ZDXLZ_Tianyan, qcis_fn) def test_get_from_hub(self): def single(backend_type, simulator_class): @@ -74,6 +78,7 @@ class Test_backends: single(BackendType.QUALESIM_QUANTUMSIM, QuaLeSim_quantumsim) single(BackendType.QUALESIM_TEQUILA, QuaLeSim_tequila) single(BackendType.SYMQC, IfSymQC) + single(BackendType.TIANYAN, ZDXLZ_Tianyan) if __name__ == "__main__": diff --git a/unittest/backends/test_tianyan.py b/unittest/backends/test_tianyan.py new file mode 100644 index 0000000..20aa3e0 --- /dev/null +++ b/unittest/backends/test_tianyan.py @@ -0,0 +1,26 @@ +from pathlib import Path + +from quingo.backend.backend_hub import BackendType +from quingo.backend.qisa import Qisa +from quingo.backend.tianyan import ZDXLZ_Tianyan +from quingo.core.exe_config import * + +cur_dir = Path(__file__).parent +qcis_fn = cur_dir / ".." / "test_qcis" / "bell_cz.qcis" + + +def test_execute(): + platform = ZDXLZ_Tianyan() + platform.upload_program(qcis_fn) + exe_config = ExeConfig( + mode=ExeMode.RealMachine, + num_shots=1000, + qcloud_platform_login_key="55kGV2wrhSuZjzhR+rmhhiavICd+KYZo9WmHav8+4ng=", + qcloud_machine_name="tianyan24", + ) + res = platform.execute(exe_config) + print(res) + + +if __name__ == "__main__": + test_execute() diff --git a/unittest/test_qcis/bell_cz.qcis b/unittest/test_qcis/bell_cz.qcis new file mode 100644 index 0000000..6bb88f7 --- /dev/null +++ b/unittest/test_qcis/bell_cz.qcis @@ -0,0 +1,6 @@ + H Q14 + H Q15 + CZ Q14 Q15 + H Q15 + M Q14 + M Q15 \ No newline at end of file -- Gitee From 473d4adc8879d8ffda8c71c62af941224eb6e7e0 Mon Sep 17 00:00:00 2001 From: Xiang Fu Date: Wed, 6 Aug 2025 20:15:49 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E2=9C=A8feat(cl):=20=E9=BB=98=E8=AE=A4?= =?UTF-8?q?=E4=BD=BF=E7=94=A8=E6=96=B0=E7=89=88quingoc=E5=89=8D=E7=AB=AF?= =?UTF-8?q?=E6=9D=A5=E7=BC=96=E8=AF=91quingo=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/quingo/core/compile.py | 2 ++ unittest/backends/test_tianyan.py | 18 +++++++++++++----- unittest/test_compile_cmd.py | 13 +++++++------ 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/src/quingo/core/compile.py b/src/quingo/core/compile.py index b49bff7..d194c7c 100644 --- a/src/quingo/core/compile.py +++ b/src/quingo/core/compile.py @@ -103,6 +103,7 @@ def compose_cl_cmd( cmd_eles = [ cl_path, + "-u", cl_entry_fn, opt_inc_dirs, config_fn, @@ -114,6 +115,7 @@ def compose_cl_cmd( opt_out_fn, ] + compile_cmd = " ".join([ele for ele in cmd_eles if ele.strip() != ""]) return compile_cmd diff --git a/unittest/backends/test_tianyan.py b/unittest/backends/test_tianyan.py index 20aa3e0..81d8b82 100644 --- a/unittest/backends/test_tianyan.py +++ b/unittest/backends/test_tianyan.py @@ -14,12 +14,20 @@ def test_execute(): platform.upload_program(qcis_fn) exe_config = ExeConfig( mode=ExeMode.RealMachine, - num_shots=1000, - qcloud_platform_login_key="55kGV2wrhSuZjzhR+rmhhiavICd+KYZo9WmHav8+4ng=", - qcloud_machine_name="tianyan24", + num_shots=10, + qcloud_platform_login_key="95hoNFTHmKqtXNi5gGUAjS7As2l8xm5Ymze1DHZFJx4=", + qcloud_machine_name="tianyan_sw", ) - res = platform.execute(exe_config) - print(res) + results = platform.execute(exe_config) + # assert isinstance(results, list) + # res = results[0] + # assert "resultStatus" in list(res.keys()) + # assert "probability" in list(res.keys()) + # assert ( + # len(res["probability"]) == 2 + # and "00" in res["probability"] + # and "11" in res["probability"] + # ) if __name__ == "__main__": diff --git a/unittest/test_compile_cmd.py b/unittest/test_compile_cmd.py index 9b27dc3..398ac88 100644 --- a/unittest/test_compile_cmd.py +++ b/unittest/test_compile_cmd.py @@ -25,13 +25,14 @@ class TestCompileCmd: mlir_path = Path(get_mlir_path()) cmd = compose_cl_cmd(task, qasm_fn, mlir_path) cmd_eles = cmd.split() - assert len(cmd_eles) == 12 + assert len(cmd_eles) == 13 assert mlir_path.resolve().samefile(cmd_eles[0].strip('"')) - assert cmd_eles[1] == '"{}"'.format(task.cl_entry_fn.resolve()) - assert cmd_eles[2] == "-I" - assert cmd_eles[4] == "-I" - assert cmd_eles[9] == "--isa=qcis" - assert cmd_eles[10] == "-o" + assert cmd_eles[1] == '-u' + assert cmd_eles[2] == '"{}"'.format(task.cl_entry_fn.resolve()) + assert cmd_eles[3] == "-I" + assert cmd_eles[5] == "-I" + assert cmd_eles[10] == "--isa=qcis" + assert cmd_eles[11] == "-o" # assert Path(qasm_fn).samefile(cmd_eles[8].strip('"')) def test_compile(self): -- Gitee From 31ff3fecd09c04f209f6949597f68a3509908643 Mon Sep 17 00:00:00 2001 From: Xiang Fu Date: Thu, 7 Aug 2025 15:25:38 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E7=89=88=E6=9C=AC?= =?UTF-8?q?=E5=8F=B7=E8=87=B30.3.5=EF=BC=8C=E6=96=B0=E5=A2=9E.gitignore?= =?UTF-8?q?=E5=92=8Cconfig/README.md=E6=96=87=E4=BB=B6=EF=BC=8C=E8=B0=83?= =?UTF-8?q?=E6=95=B4=E6=B5=8B=E8=AF=95=E6=96=87=E4=BB=B6=E8=B7=AF=E5=BE=84?= =?UTF-8?q?=E4=BB=A5=E4=BD=BF=E7=94=A8token=E6=96=87=E4=BB=B6=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/.gitignore | 1 + config/README.md | 8 ++++++++ setup.py | 2 +- src/quingo/global_config.py | 4 +++- unittest/backends/test_tianyan.py | 6 ++++-- 5 files changed, 17 insertions(+), 4 deletions(-) create mode 100644 config/.gitignore create mode 100644 config/README.md diff --git a/config/.gitignore b/config/.gitignore new file mode 100644 index 0000000..ffc1da3 --- /dev/null +++ b/config/.gitignore @@ -0,0 +1 @@ +*.tokens \ No newline at end of file diff --git a/config/README.md b/config/README.md new file mode 100644 index 0000000..5497395 --- /dev/null +++ b/config/README.md @@ -0,0 +1,8 @@ +请在此文件下保存在对接各云平台时使用的token,这些token可用于测试。此文件夹中`*.tokens`文件不会被git同步。 + +云平台与文件名的对应关系如下: + +| 云平台 | token文件名 | +|---|---| +| 中电信天衍量子云平台 | `tianyan.tokens` | +| 国盾量子云平台 | `quantumctek.tokens` | diff --git a/setup.py b/setup.py index edb2f7d..ae980f9 100755 --- a/setup.py +++ b/setup.py @@ -6,7 +6,7 @@ with open("README.md", "r", encoding="utf-8") as fh: setup( name="quingo", - version="0.3.4", + version="0.3.5", author="Xiang Fu", author_email="gtaifu@gmail.com", description="Quingo Runtime System", diff --git a/src/quingo/global_config.py b/src/quingo/global_config.py index af5db04..a535d34 100755 --- a/src/quingo/global_config.py +++ b/src/quingo/global_config.py @@ -1,6 +1,8 @@ from pathlib import Path -qgrtsys_root_dir = Path(__file__).absolute().parent +qgrtsys_root_dir = Path(__file__).absolute().parent # corresponds to `/src/quingo` +qgrtsys_repo_dir = qgrtsys_root_dir.parent.parent # corresponds to `` + mlir_compiler_config_path = qgrtsys_root_dir / "core" / "mlir_compiler_path.txt" default_mlir_compiler_path = Path.home() / ".quingo" / "quingoc" diff --git a/unittest/backends/test_tianyan.py b/unittest/backends/test_tianyan.py index 81d8b82..7edf4a1 100644 --- a/unittest/backends/test_tianyan.py +++ b/unittest/backends/test_tianyan.py @@ -4,9 +4,11 @@ from quingo.backend.backend_hub import BackendType from quingo.backend.qisa import Qisa from quingo.backend.tianyan import ZDXLZ_Tianyan from quingo.core.exe_config import * +from quingo.global_config import qgrtsys_repo_dir cur_dir = Path(__file__).parent -qcis_fn = cur_dir / ".." / "test_qcis" / "bell_cz.qcis" +qcis_fn = qgrtsys_repo_dir / "unittest" / "test_qcis" / "bell_cz.qcis" +token_fn = qgrtsys_repo_dir / "config" / "tianyan.tokens" def test_execute(): @@ -15,7 +17,7 @@ def test_execute(): exe_config = ExeConfig( mode=ExeMode.RealMachine, num_shots=10, - qcloud_platform_login_key="95hoNFTHmKqtXNi5gGUAjS7As2l8xm5Ymze1DHZFJx4=", + qcloud_platform_login_key=token_fn.read_text().strip(), qcloud_machine_name="tianyan_sw", ) results = platform.execute(exe_config) -- Gitee