QPanda

  QPanda (Quantum Programming Architecture for NISQ Device Applications)是一个高效、便捷的量子计算开发工具库,为了让用户更容易的使用 QPanda,更便捷的进行量子 编程,它屏蔽了复杂的 C++语法结构,甚至用户不需要了解所谓的面向对象,只需要学会如何把量子编程中用到的接口调用一遍就可以进行量子计算。

  例:如何构造一个量子程序,并在量子虚拟机中运行它。

  首先假设有一台量子计算机,它有 2 个量子比特: 𝑄1、 𝑄2,接着对其中一个量子比特(𝑄1)进行 H 门操作, 构造了一个量子叠加态; 并对𝑄1和𝑄2做𝐶𝑁𝑂𝑇门操作, 𝑄1为控制量子比特, 𝑄2为目标量子比特, 最后对所有的量子比特进行测量操作。 此时,将有 50% 的概率得到 00 或者 11 的测量结果。 代码示例如下:

#include "QPanda.h"
#include <stdio.h>
using namespace QPanda;
int main(){
    init(QMachineType::CPU); /* 初始化一个基于 CPU 计算的量子虚拟机*/
    QProg prog; /* 构造一个量子程序*/
    auto q = qAllocMany(2); /* 申请两个量子比特*/
    auto c = cAllocMany(2); /* 申请两个经典比特*/
    prog << H(q[0]) /* 向量子程序中插入 H 门、 CNOT 门和Measure*/
    << CNOT(q[0],q[1])
    << MeasureAll(q, c);
    auto results = runWithConfiguration(prog, c, 1000);/* 让量子程序在量子虚拟机中跑 1000 次*/
    for (auto result : results) { /* 循环输出结果*/
        printf("%s : %d\n", result.first.c_str(), result.second);
    }
    finalize();
}

  这是个简单却能体现出量子计算特点的例子,它即体现了量子态叠加,又体现量子比特纠缠。 从上例可以看到,用户实质上只需要关注如何使用 QPanda 构建量子程序,其他的细节操作完全不需要用户操心。

  再例如,在很多量子算法如 QAOA 算法中,都需要构造一组量子比特的叠加态, 那么完全可以把这种操作抽象成一种生成量子线路的函数,输入是一组量子比特,输出是一个量子线路。代码示例如下:

#include "QPanda.h"
#include <stdio.h>
using namespace QPanda;

QCircuit HadamardCircuit(QVec & qvec) {
    QCircuit qcircuit; /* 构造一个量子线路*/
    for (auto aiter : qvec) { /* 对传入的量子比特做 H 门操作*/
        qcircuit<<H(aiter); /* 把 H 门插入的量子线路中*/
    }
    return qcircuit; /* 返回量子线路*/
}

int main() {
    init(QMachineType::CPU); /* 初始化一个基于 CPU 计算的量子虚拟机*/
    QProg prog; /* 构造一个量子程序*/
    auto q = qAllocMany(2); /* 申请两个量子比特*/
    auto c = cAllocMany(2); /* 申请两个经典比特*/
    prog << HandmadeCircuit(q) /* 调用 HadamardCircuit 函数,并把生成的量子线路插入到量子程序中*/
    auto results = runWithConfiguration(prog, c, 1000);/* 让量子程序在量子虚拟机中跑 1000 次*/
    for (auto result : results){ /* 循环输出结果*/
        printf("%s : %d\n", result.first.c_str(), result.second);
    }
    finalize();
}

  从上述两例可以知道,用户只需要关注量子程序的构建,其他的部分,如量子虚拟机的构建、 申请量子比特、执行量子程序和获取结果,都是一个固定的流程,只需要调用函数接口即可。

  深入了解 QPanda 的使用,就必须要了解一下 QPanda 中与量子计算相关的数据类型: QGate(量子逻辑门), Measure(测量), ClassicalProg(经典程序), QCircuit(量子线路),Qif(量子条件判断程序), QWhile(量子循环程序), QProg(量子程序);

  QGate:量子逻辑门是量子计算的基本单位,任何一个量子程序都是由 QGate 组合而成,如果说量子程序或量子算法是一套拳法, 那么 QGate 就是一个个被拆解出来的动作,几个 QGate 的固定组合就是一个招式,它们的最终目的就是把这套拳法打出来。

  QPanda 2 把所有的量子逻辑门封装为 API 向用户提供使用,并可获得 QGate 类型的返回值。 例如,如果想使用 Hadamard 门,就可以通过如下方式获得:

QGate h = H(qubit);

可以看到, H 函数只接收一个 qubit, qubit 如何申请请参考

https://QPanda 2.readthedocs.io/zh_CN/latest/TotalAmplitude.html#quantummachine

再例如,想要使用 RX 门,可以通过如下方式获得:

QGate rx = RX(qubit, PI);

  如上所示, RX 门接收两个参数,第一个是目标量子比特,第二个偏转角度,也可以通过相同的方式使用 RY, RZ 门。

  两比特量子逻辑门的使用和单比特量子逻辑门的用法相似,只不过是输入的参数不同,举个使用 CNOT 的例子:

QGate cnot = CNOT(control_qubit, target_qubit);

  CNOT 门接收两个参数,第一个是控制比特,第二个是目标比特。

  Measure:它的的作用是对量子比特进行测量操作。

  在量子程序中需要对某个量子比特做测量操作,并把测量结果存储到经典寄存器上,可以通过下面的方式获得一个测量对象:

auto measure = Measure(qubit, cbit);

  可以看到 Measure 接两个参数, 第一个是测量比特,第二个是经典寄存器。   如果想测量所有的量子比特并将其存储到对应的经典寄存器上,可以如下操作:

auto measure_all = MeasureAll(qubits, cbits);
# MeasureAll 的返回值类型是 QProg

  其中 qubits 的类型是 QVec , cbits 的类型是 vector。   在得到含有量子测量的程序后,可以调用 directlyRun 或 runWithConfiguration 来得到量子程序的测量结果。

  directlyRun 的功能是运行量子程序并返回运行的结果, 使用方法如下:

QProg prog;
prog << H(qubits[0])
    << CNOT(qubits[0], qubits[1])
    << CNOT(qubits[1], qubits[2])
    << CNOT(qubits[2], qubits[3])
    << Measure(qubits[0], cbits[0]);

auto result = directlyRun(prog);

  runWithConfiguration 的功能是末态目标量子比特序列在量子程序多次运行结果中出现的次数, 使用方法如下:

QProg prog;
    prog << H(qubits[0])
    << H(qubits[1])
    << H(qubits[2])
    << H(qubits[3])
    << MeasureAll(qubits, cbits); // 测量所有的量子比特

auto result = runWithConfiguration(prog, cbits, 1000);

  其中第一个参数是量子程序,第二个参数是经典寄存器, 第三个参数是运行的次数。实例:

#include <QPanda.h>
USING_QPANDA

int main(void){
    auto qvm = initQuantumMachine();
    auto qubits = qvm->allocateQubits(4);
    auto cbits = qvm->allocateCBits(4);
    QProg prog;

    prog << H(qubits[0])
        << H(qubits[1])
        << H(qubits[2])
        << H(qubits[3])
        << MeasureAll(qubits, cbits);

    auto result = quickMeasure(prog, 1000);
    for (auto &val: result){
        std::cout << val.first << ", " << val.second << std::endl;
    }

    qvm->finalize();
    delete qvm;

    return 0;
}

  运行结果:

0000, 47
0001, 59
0010, 74
0011, 66
0100, 48
0101, 62
0110, 71
0111, 61
1000, 70
1001, 57
1010, 68
1011, 63
1100, 65
1101, 73
1110, 55
1111, 61
  • ClassicalProg: 经典程序也可以被插入到量子程序中,它使得量子程序也可以进行逻辑判断和简单的经典计算,使得量子程序更灵活。打个比方,就像是向一套拳法中加入了步法,使得这套拳法可以辗转腾挪。
  • QCircuit: 量子线路是由多个量子逻辑门组成的,或者说量子线路是一个大型的量子逻辑门,也就是说 QCircuit 中可以插入 QGate 和 ClassicalProg。如果映射到功夫中,QCircuit 就是拳法中拆解出来的套路。
  • Qif: 量子条件判断程序,顾名思义,它可以让量子程序进行逻辑判断,即针对不同的对手拳法的套路也是可变的。
  • QWhile: 量子循环判断程序,即根据循环判断条件把一个量子程序或量子线路多次运行。
  • QProg: 它是一个容器,可以容纳所有量子计算相关的数据类型,在构造量子程序时,用户可以把 QGate、 QCircuit、 Qif、 QWhile、 QProg、 ClassicalProg 类型插入到 QProg 中。

  QPanda 的特点不仅仅体现着它的易用性,还包括它的高效, 如图 4.1.1, 在同等硬件配置下, QPanda 的量子虚拟机运行量子程序的速度,相对其他工具有着巨大优势。

图 4.1.1.1 量子虚拟机性能图(quantum gate simulation runtime-量子门运行模拟状态)

图 4.1.1.1 量子虚拟机性能图(quantum gate simulation runtime-量子门运行模拟状态

除此之外, QPanda 还集成了量子程序优化器、量子程序调试工具,量子程序编译器。 + 量子程序优化器: QPanda 的优化器通过特有的算法对量子程序的优化,可最大限度的减少计算时间。 + 量子程序调试工具: QPanda 的调试工具解决的量子算法工程师长期以来的困扰,里程碑的实现类量子程序的调试功能。 + 量子程序编译器: 不仅把量子程序转换为多种量子汇编语言,更可以生成量子程序可执行文件。