关键要点:

Qiskit的C API让开发者能够直接从Fortran、C++和Julia语言中调用Qiskit,无需Python环境,这得益于该SDK底层高性能Rust核心的开放。

自Qiskit v2.0版本起,一个统一的C接口将SDK的Rust核心与高性能计算(HPC)和科学计算领域几乎所有常用编程语言连接起来。

由于所有语言绑定共享同一个Qiskit库,它们之间可以互相操作:比如在Fortran中构建的电路,可以直接传递给C++程序使用。

原生语言绑定使得将Qiskit集成到混合量子-经典HPC工作流程中变得更加简便,有助于推动量子计算在优化、机器学习和科学模拟领域的应用。

Qiskit是全球最受欢迎的量子计算软件开发工具包,大多数人通过Python编程语言接触到它。但Python并非唯一的入口。

自Qiskit v2.0版本开始,该SDK向其核心数据模型开放了C API接口——这正是驱动Python SDK的那套高性能Rust核心。由于C语言几乎能与所有编程语言实现互操作,这个统一接口也为许多其他语言打开了大门。其中三种语言——Fortran、C++和Julia——现在可以让开发者用日常使用的编程语言直接处理量子电路。这意味着量子计算能够直接融入现有代码体系,不再需要额外的Python层。

更重要的是,由于每种语言绑定都基于同一个Qiskit共享库,它们之间也具备互操作性。理论上,开发者可以在Fortran中构建一个电路,再将其传递给C++程序。由于两种语言绑定都指向同一个对象,这一过程应当能顺畸运行。

这些接口之所以重要,是因为我们相信量子计算将成为科学计算领域的一场革命性变革。正如IBM及其合作伙伴近期的演示所展现的那样,量子计算的优势在于与经典计算资源相结合,而非孤立存在。

多年来,研究人员一直在探索利用量子方法解决优化、机器学习以及复杂量子系统和动力学模拟等问题。这些研究工作中,很大一部分并非使用Python语言完成。

即便Python驱动整个工作流程,物理、化学和工程领域许多模拟代码中计算密集的核心部分,通常仍是用Fortran和C++编写的,并且越来越多地采用Julia语言。在许多HPC社区中,这些语言承载着科学计算的核心逻辑,而shell或Python脚本仅仅起到协调各部分的作用。

探索量子计算不应迫使从事经典应用研究的科研人员在现有代码基础上强行嵌入Python解释器。为了帮助研究界充分挖掘量子计算的潜力,我们必须确保无论使用哪种编程语言,都能轻松地将Qiskit集成到混合量子-经典工作流程中。

准备好体验原生Qiskit代码能为你的研究带来什么了吗?在IBM Quantum Platform上创建免费账户,即可在真实量子硬件上运行实验,并查阅文档了解如何将Qiskit引入你的Fortran、C++和Julia工作流程。

通往Qiskit的三条路径:Fortran、C++与Julia

进入Qiskit的三条路径各有不同,但它们拥有共同的基础:每一种都绑定到C API,并直接与Qiskit的Rust核心通信。更重要的是,每一种语言绑定都力求以最贴合该语言社区习惯的方式呈现。以下是具体实现方式:

Fortran

Fortran是最古老的高级编程语言之一。它最初是作为一种“公式翻译系统”推出的,使科学家能够直接编写数值表达式,并将其编译为高效的机器代码。

数十年后,它仍然支撑着高性能计算和科学计算领域的大量应用。核心线性代数库,如BLAS和LAPACK,都是用Fortran实现的,诸如Gaussian、VASP、Quantum ESPRESSO、CP2K、GAMESS、NWChem等主力量子化学代码,以及KSHELL、BIGSTICK和MFDn等核物理工具也是如此。

为了让量子计算更贴近这些应用领域,我们开发了qiskit-fortran,这是一个用于构建和操作量子电路的Fortran接口。它的设计经过了与Fortran开发者社区的积极讨论,确保该接口能够自然融入现有的Fortran工作流程。

在底层实现上,它通过Fortran的标准外部函数接口(iso_c_binding)绑定到Qiskit的C API,直接调用C API函数,因此开发者不必自行编写绑定代码。这些调用直接触达驱动Python SDK的同一个Rust核心,全程无需经过Python。

在qiskit-fortran中,QuantumCircuit是一种派生类型,带有FINAL析构器,这意味着当变量超出作用域时,电路会自动释放其占用的内存。开发者可以专注于物理问题本身:例如,一个来自GAMESS、已驻留在Fortran内存中的FCIDUMP活性空间哈密顿量,可以直接以指针形式传递给Qiskit的电路构建程序——无需复制到Python对象中,不涉及GIL锁,也无需重新分配内存。

通过保持工作流程的原生性,我们消除了对中间Python层的依赖,为与现有Fortran应用程序实现更紧密、更高效的集成创造了条件。

在我们的qiskit-fortran教程中可以找到详细的示例工作流程。

C++

C++编程语言最初是作为C语言的扩展而诞生的,增加了类的概念,在不增加运行时开销的情况下提供了高层次的抽象能力。这使它成为性能关键型模拟计算的主力语言,应用范围从LAMMPS、GROMACS等分子动力学软件,到CUDA、Kokkos等用于编程当今exascale超级计算机的加速层。

qiskit-cpp于去年首次发布,是一个仅含头文件的C++接口,用于调用Qiskit的C API。开发者只需将其头文件添加到包含路径中,将程序链接到Qiskit的C库,并从Qiskit源代码树中编译一次即可。

在这里,QuantumCircuit是一个C++对象,其语法与我们在Python中使用的非常接近,并且在超出作用域时会自动释放自身占用的内存。执行方式也十分灵活:电路可以通过qiskit-ibm-runtime的C客户端、QRMI或SQC来提交。

可以在qiskit-cpp教程中找到示例工作流程。

Julia

Julia是一种旨在兼具编译型语言的速度与动态语言的易用性的编程语言。在许多方面,它为在Python之外使用Qiskit提供了最平缓的学习曲线。它无需从源代码构建,并且可以在Jupyter notebook中运行,因此开发者可以像在Python中一样进行交互式操作。

Qiskit.jl对Qiskit的C API进行了封装,并将其作为原生Julia类型暴露出来,因此开发者无需自行处理C指针的管理问题。电路构建的语法与Python中的语法相似,但该软件包也提供了符合Julia语言习惯的风格供用户选择。同样的绑定策略也延伸到了电路执行环节:QiskitIBMRuntime.jl是qiskit-ibm-runtime C客户端的轻量级封装,用于向IBM Quantum硬件提交电路并获取结果。

借助这两个软件包,开发者现在可以完全用Julia语言运行一套完整的量子工作流程,并将其与Julia生态系统的其他部分连接起来。该生态系统为科学计算提供了多种实用工具,包括DifferentialEquations.jl等微分方程求解器,以及Optimization.jl等优化库。

Julia生态系统还提供了许多与量子计算相关的工具,包括ITensors.jl和TensorNetworkQuantumSimulator.jl等张量网络模拟工具——这些都是将量子计算结果与近似经典模拟进行对比验证的宝贵资源。

入门实践:在100个量子比特上模拟量子动力学

为了让大家更直观地了解在Python之外使用Qiskit是什么体验,让我们通过一个简短的教程更深入地了解Qiskit.jl。我们将介绍如何使用量子方法求解薛定谔方程来构建电路并在硬件上执行——该方程描述了量子系统在其哈密顿量(一个描述系统并生成其时间演化的数学对象)作用下随时间演化的过程。

量子计算机天生适合求解薛定谔方程:它们只需演化编码在量子比特中的量子态即可。由于这种演化必须通过离散的量子门来实现,我们通过一种称为Trotter分解的过程来对其进行近似,即将整个动力学过程拆分为许多微小的步骤。步长越小,离散化误差越低,但需要运行的电路也就越深。

测试系统选用的是横向场伊辛模型——一个具有最近邻耦合的一维自旋链,从初始的奈尔态|0101…?开始演化。接下来的工作流程与大多数量子工作流程一致,分为四个步骤:(1)将问题映射为电路,(2)针对硬件优化该电路,(3)在硬件上执行,(4)对结果进行后处理。

唯一的区别在于,这里的每一步都在Julia语言中运行。

第一步:将问题映射为电路。每一个Trotter步骤都会转化为一层单量子比特Rx旋转门和双量子比特Rzz门。在Qiskit.jl中,电路是一个原生的Julia对象,其构建API采用符合Julia语言习惯的写法——使用带有!后缀的可变函数,并将电路作为其第一个参数,同时几乎与Python SDK中的语法逐行对应:

```

using Qiskit using Qiskit.Operations function make_trotter_circuit(h, J, n, δt, steps) qc = QuantumCircuit(n, n) for i in 1:2:n x!(qc, i) end # 准备奈尔态 |0101…? for _ in 1:steps # 一个二阶Trotter步骤 for i in 1:n rx!(qc, h[i] * δt, i) end for i in 1:n-1 rzz!(qc, 2J[i] * δt, i, i+1) end for i in 1:n rx!(qc, h[i] * δt, i) end end for i in 1:n measure!(qc, i, i) end return qc end

```

复制到剪贴板

如果开发者曾用Python构建过Qiskit电路,就会发现rx!(qc, θ, i)和rzz!(qc, θ, i, j)可以直接对应到qc.rx(θ, i)和qc.rzz(θ, i, j)。唯一需要注意的是索引方式:Julia中量子比特的计数从1开始,这是Julia语言的惯例,而Python则从0开始计数。

Q&A

Q1:Qiskit的C API是什么?它有什么用?

A:Qiskit的C API是自Qiskit v2.0版本起开放的接口,它连接了SDK底层的高性能Rust核心。通过这个统一接口,Fortran、C++、Julia等多种编程语言都能直接调用Qiskit,无需依赖Python环境,便于集成到混合量子-经典计算工作流程中。

Q2:不同语言绑定的Qiskit电路能否互相传递使用?

A:可以。由于Fortran、C++、Julia等语言绑定都基于同一个Qiskit共享库,它们之间具备互操作性。理论上,开发者可以在Fortran中构建一个量子电路,再将其传递给C++程序使用,因为两种语言绑定都指向同一个底层对象。

Q3:为什么要为Fortran、C++和Julia开发原生Qiskit接口?

A:因为许多科学计算和高性能计算领域的核心代码是用Fortran、C++编写的,物理、化学、工程领域的模拟程序尤其依赖这些语言。原生接口让研究人员无需在现有代码中强行嵌入Python解释器,就能直接使用Qiskit进行量子计算实验。

IBM