5.3 使用单振幅和部分振幅量子虚拟机

5.3.1 单振幅量子虚拟机

  目前可以通过量子计算的相关理论,用经典计算机实现模拟量子虚拟机。 量子虚拟机的模拟主要有全振幅与单振幅两种解决方案,其主要区别在于,全振幅一次模拟计算就能算出量子态的所有振幅,单振幅一次模拟计算只能计算出 \(2^N\) 个振幅中的一个。

  然而全振幅模拟量子计算时间较长,计算量随量子比特数指数增长,在现有硬件下,无法模拟超过49量子比特。通过单振幅量子虚拟机技术可以模拟超过49比特,同时模拟速度有较大提升,且算法的计算量不随量子比特数指数提升。

使用介绍

  QPanda2中设计了 SingleAmplitudeQVM 类用于运行单振幅模拟量子计算,同时提供了相关接口,它的使用也很简单。

  首先构建一个单振幅量子虚拟机:

1.auto machine = new SingleAmplitudeQVM();

  然后必须使用 SingleAmplitudeQVM::init() 初始化量子虚拟机环境:

1.machine->init();

  接着进行量子程序的构建、装载工作:

1.auto prog = QProg();
2.auto qlist = machine->qAllocMany(10);
3.auto clist = machine->cAllocMany(10);
4.
5.for_each(qlist.begin(), qlist.end(), [&](Qubit *val) { prog << H(val); });
6.prog << CZ(qlist[1], qlist[5]) << CZ(qlist[3], qlist[5]) << CZ(qlist[2], qlist[4]);
7....
8.machine->directlyRun(prog);

  最后调用计算接口,设计多种返回值的接口用于满足不同的计算需求,具体见示例所述:

实例

1.#include "QPanda.h"
2.USING_QPANDA
3.
4.int main(void)
5.{
6.    auto machine  = new SingleAmplitudeQVM();
7.    machine->init();
8.
9.    auto prog  = QProg();
10.    auto qlist = machine->qAllocMany(10);
11.    auto clist = machine->cAllocMany(10);
12.
13.    for_each(qlist.begin(), qlist.end(), [&](Qubit *val) { prog  << H(val); });
14.    prog  << CZ(qlist[1], qlist[5])
15.        << CZ(qlist[3], qlist[5])
16.        << CZ(qlist[2], qlist[4])
17.        << CZ(qlist[3], qlist[7])
18.        << CZ(qlist[0], qlist[4])
19.        << RY(qlist[7], PI  / 2)
20.        << RX(qlist[8], PI  / 2)
21.        << RX(qlist[9], PI  / 2)
22.        << CR(qlist[0], qlist[1], PI)
23.        << CR(qlist[2], qlist[3], PI)
24.        << RY(qlist[4], PI  / 2)
25.        << RZ(qlist[5], PI  / 4)
26.        << RX(qlist[6], PI  / 2)
27.        << RZ(qlist[7], PI  / 4)
28.        << CR(qlist[8], qlist[9], PI)
29.        << CR(qlist[1], qlist[2], PI)
30.        << RY(qlist[3], PI  / 2)
31.        << RX(qlist[4], PI  / 2)
32.        << RX(qlist[5], PI  / 2)
33.        << CR(qlist[9], qlist[1], PI)
34.        << RY(qlist[1], PI  / 2)
35.        << RY(qlist[2], PI  / 2)
36.        << RZ(qlist[3], PI  / 4)
37.        << CR(qlist[7], qlist[8], PI);
38.
39.    machine->directlyRun(prog);
40.    auto res = machine->getProbDict(qlist);
41.    cout << res["0000000000"] << endl;
42.    cout << res["0000000001"] << endl;
43.    delete(machine);
44.    return 0;
45.}

  getProbDict()接口表示输出计算后的量子态概率,输出结果用map容器保存,key为量子态对应的字符串,value为对应的概率,上述程序的计算结果如下:

1.0.00166709
2.0.00166709

  若使用其他接口:

  · getProbDict(qvec,std::string) ,使用示例:

1.QVec qvec;
2.for_each(qlist.begin(), qlist.end(), [&](Qubit *val) { qvec.emplace_back(val); });
3.machine->directlyRun(prog);
4.auto res = machine->getProbDict(qlist);
5.for (auto val : res)
6.{
7.std::cout << val.first << " : " << val.second << std::endl;
8.}

  结果输出如下:

1.0000000000 : 0.0016671
2.0000000001 : 0.0016671
3.0000000010 : 0.000286029
4.0000000011 : 0.000286029
5.0000000100 : 0.000286029
6.0000000101 : 0.000286029
7.......

 · pMeasureBinindex(std::string) ,使用示例:

1.auto res = machine->pMeasureBinindex("0000000001");
2.std::cout << res << std::endl;

  通过二进制形式下标测量指定振幅,结果输出如下:

1.(0.0408301,-7.80626e-18)

  · pMeasureDecindex(std::string) ,使用示例:

1.auto res = PMeasure_bin_index("1");
2.std::cout << res << std::endl;

  通过十进制形式下标测量指定振幅,结果输出如下

1.0.00166709

5.3.2 部分振幅量子虚拟机

  目前用经典计算机模拟量子虚拟机的主流解决方案有全振幅与单振幅两种。除此之外,还有部分振幅量子虚拟机,该方案能在更低的硬件条件下,实现更高的模拟效率。 部分振幅算法的基本思想是将大比特的量子计算线路图拆分成若干个小比特线路图,具体数量视线路扶持情况而定。

使用介绍

  QPanda2中设计了 PartialAmplitudeQVM 类用于运行部分振幅模拟量子计算,同时提供了相关接口,它的使用很简单。

  首先构建一个部分振幅量子虚拟机:

1.auto machine = new PartialAmplitudeQVM();

  然后必须使用 PartialAmplitudeQVM::init() 初始化量子虚拟机环境:

1.machine->init();

  接着进行量子程序的构建、装载工作:

1.auto prog = QProg();
2.auto qlist = machine->qAllocMany(10);
3.auto clist = machine->cAllocMany(10);
4.
5.for_each(qlist.begin(), qlist.end(), [&](Qubit *val) { prog << H(val); });
6.prog << CZ(qlist[1], qlist[5]) << CZ(qlist[3], qlist[5]) << CZ(qlist[2], qlist[4]);
7....
8.machine->directlyRun(prog);

  最后调用计算接口,设计多种返回值的接口用于满足不同的计算需求,具体见示例所述:

实例

  以下示例展示了部分振幅量子虚拟机接口的使用方式:

1.#include "QPanda.h"
2.USING_QPANDA
3.
4.int main(void)
5.{
6.    auto machine = new PartialAmplitudeQVM();
7.    machine->init();
8.
9.    auto prog = QProg();
10.    auto qlist = machine->qAllocMany(10);
11.    auto clist = machine->cAllocMany(10);
12.
13.    auto prog = QProg();
14.    for_each(qlist.begin(), qlist.end(), [&](Qubit *val) { prog << H(val); });
15.    prog << CZ(qlist[1], qlist[5])
16.         << CZ(qlist[3], qlist[7])
17.         << CZ(qlist[0], qlist[4])
18.         << RZ(qlist[7], PI / 4)
19.         << RX(qlist[5], PI / 4)
20.         << RX(qlist[4], PI / 4)
21.         << RY(qlist[3], PI / 4)
22.         << CZ(qlist[2], qlist[6])
23.         << RZ(qlist[3], PI / 4)
24.         << RZ(qlist[8], PI / 4)
25.         << CZ(qlist[9], qlist[5])
26.         << RY(qlist[2], PI / 4)
27.         << RZ(qlist[9], PI / 4)
28.         << CR(qlist[2], qlist[7], PI / 2);
29.
30.    machine->directlyRun(prog);
31.    auto res = machine->getProbDict(qlist);
32.    cout << res["0000000000"] << endl;
33.    cout << res["0000000001"] << endl;
34.    delete(machine);
35.    return 0;
36.}

  上述程序的计算结果如下:

1. 0.0016671
2. 0.0016671

  若使用其他接口:

  · PMeasure_bin_index(std::string) ,使用示例:

1.auto res = machine->PMeasure("6");
2.for (auto val :res)
3.{
4.    std::cout << val.first << " : " << val.second << std::endl;
5.}

  结果输出如下:

1. 0.00166709

  · getProbDict(qvec,std::string) ,使用示例:

1.QVec qvec;
2.for_each(qlist.begin(), qlist.end(), [&](Qubit *val) { qvec.emplace_back(val); });
3.
4.auto res = machine->getProbDict(qlist);
5.for (auto val : res)
6.{
7.    std::cout << val.first << " : " << val.second << std::endl;
8.}

  结果输出如下:

1.0000000000 : 0.0016671
2.0000000001 : 0.0016671
3.0000000010 : 0.000286029
4.0000000011 : 0.000286029
5.0000000100 : 0.000286029
6.0000000101 : 0.000286029

  · pmeasure_bin_index(std::string) ,使用示例:

1.auto res = machine->pmeasure_bin_index("0000000001");
2.    std::cout << res << std::endl;

  通过二进制形式下标测量指定振幅,结果输出如下:

1. (0.0408301,-7.80626e-18)

  · pmeasure_dec_index(std::string) ,使用示例:

1.auto res = machine->pmeasure_dec_index("6");
2.std::cout << res << std::endl;

  通过十进制形式下标测量指定振幅,结果输出如下:

1.(-4.33681e-18,-0.0408301)