cudaq spec 02,03,命名空间与标准,

 

2. 命名空间与标准

[1] CUDA-Q 语言是基于 C++ 的库扩展。因此,所有相关数据结构和库函数都存在于 CUDA-Q 命名空间内。该命名空间表示为 ::cudaq

[2] cudaq::contrib 命名空间包含由更广泛的社区贡献的功能。虽然这些功能提供了实用的能力,并在各版本中保持维护,但其功能可能较为有限,且可能无法覆盖某些场景。如果您遇到问题或希望请求更广泛的功能,请提交 GitHub Issue,我们将在未来的版本中予以考虑。

[3] CUDA-Q 是一个遵循 C++20 语言规范的、基于 C++ 库的语言扩展。任何需要向后兼容旧标准的实现,都必须保持面向用户的 API 的语义不变(例如,使用 SFINAE 而非概念和约束)。

3. 量子类型

CUDA-Q 语言扩展提供了一些与量子-经典计算相关的基本类型。这些类型通过 C++ 中 cudaq 命名空间内定义的经典库类型提供。

3.1. cudaq::qudit<Levels>

[1] cudaq::qudit 模拟一个 N 级的量子信息单元。该系统的状态(对于量子比特)可以用希尔伯特空间中的一个 N 维向量来描述,所有元素的绝对平方和为 1。

[2] cudaq::qudit 封装了一个唯一的 std::size_t,用于模拟量子比特在底层量子内存空间中的索引(假设有无限的可用量子比特寄存器)。

[4] 为了遵守量子力学的不可克隆定理,cudaq::qudit 不可复制且不可移动。因此,所有 cudaq::qudit 实例必须通过引用传递,并且在编译时满足不可克隆定理。

[5] cudaq::qudit 实例只能在 CUDA-Q 量子内核代码中分配,绝不能从经典主机代码中分配。

[6] 所有实例化的 cudaq::qudit 实例都从计算基态 |0> 开始,并作为模拟典型逻辑量子门操作的量子内禀操作的主要输入参数。

[7] 在量子操作调用中用作控制位时,cudaq::qudit 实例可以被取反。取反的机制应通过重载 qudit<N>::operator!() 来实现。

cudaq::qudit 采用以下结构:

template <std::size_t Levels>
class qudit {
  protected:
    const std::size_t idx = 0;
  public:
    qudit();
    qudit(const qudit&) = delete;
    qudit(qudit &&) = delete;
    std::size_t id() const;
    static constexpr std::size_t n_levels();
    qudit<Levels> &operator!();
};

3.2. cudaq::qubit

[1] 本规范提供了原始的 cudaq::qubit 类型,它模拟离散量子内存空间中的单个量子比特(2 级)。cudaq::qubit 是 cudaq::qudit<2> 的别名。

namespace cudaq {
  using qubit = qudit<2>;
}

C++ 示例:

{
  // 在 |0> 态分配一个量子比特
  cudaq::qubit q;
  // 将量子比特置于 |0> 和 |1> 的叠加态
  h(q); // cudaq::h == 阿达玛门,利用了参数依赖查找 (ADL)
  printf("ID = %lu\n", q.id()); // 输出 0
  cudaq::qubit r;
  printf("ID = %lu\n", r.id()); // 输出 1
  // 量子比特超出作用域,隐式释放
}
cudaq::qubit q;
printf("ID = %lu\n", q.id()); // 输出 0 (先前已释放)

Python 示例

# Allocate a qubit in the |0> state
q = cudaq.qubit()
# Put the qubit in a superposition of |0> and |1>
h(q)
print("ID = {}".format(q.id())) # prints 0

r = cudaq.qubit()
print("ID = {}", r.id()) # prints 1
# qubits go out of scope, implicit deallocation

3.3. 量子容器

[1] CUDA-Q 指定了以熟悉的 C++ 容器形式处理一组 cudaq::qudit 实例的抽象。

[2] 存储在这些容器中的 cudaq::qudit 实例的底层连接性对程序员是透明的,任何逻辑到物理的程序连接性映射应由编译器实现完成。

3.3.1. cudaq::qview<Levels = 2>

[1] cudaq::qview<N> 是对离散量子内存空间子集的非拥有引用,因此它是一个类似于 std::span 的 C++ 范围,包含 cudaq::qudit

[2] cudaq::qview 不拥有其元素,因此可以按值或按引用传递。

[3] cudaq::qview 根据包含的量子信息单元的维度进行模板化,对于量子比特系统默认为 2。

[4] cudaq::qview 提供了提取单个量子比特和子寄存器切片的 API。程序员可以提取前 N 个量子比特、后 N 个量子比特,以及从给定索引开始并包含用户指定数量的量子比特的内部切片。

cudaq::qview 应具有以下结构:

namespace cudaq {
  template <std::size_t Levels = 2>
  class qview {
    private:
      std::span<qudit<Levels>> qudits;
    public:
      // 构造一个引用 `other` 中量子比特的 span
      template <typename R>
      requires(std::ranges::range<R>)
      qview(R&& other);
      qview(const qview& other);

      // 迭代器接口
      auto begin();
      auto end();

      // 返回位于 `idx` 的量子比特
      qudit<Levels>& operator[](const std::size_t idx);

      // 返回前 `count` 个量子比特 [0, count)
      qview<Levels> front(std::size_t count);
      // 返回第一个量子比特
      qudit<Levels>& front();
      // 返回后 `count` 个量子比特 [count, size())
      qview<Levels> back(std::size_t count);
      // 返回最后一个量子比特
      qudit<Levels>& back();

      // 返回切片 [start, start+count) 的量子比特
      qview<Levels>
      slice(std::size_t start, std::size_t count);

      // 返回包含的量子比特数量
      std::size_t size() const;
  };
}

3.3.2. cudaq::qvector<Levels = 2>

[1] cudaq::qvector<Levels> 是离散量子内存空间元素的容器——一个 cudaq::qudit 的 C++ 容器。

[2] cudaq::qvector 是一个动态构造的拥有 cudaq::qudit 的容器(类似于 std::vector),由于它拥有量子内存,因此不能被复制或移动。

[3] cudaq::qvector 根据包含的量子信息单元的维度进行模板化,对于量子比特系统默认为 2。

[4] cudaq::qvector 只能在 CUDA-Q 内核中实例化。

[5] cudaq::qvector 中的所有量子比特都从计算基态 |0> 开始。

[6] cudaq::qvector 提供了提取单个量子比特和子寄存器切片的 API。程序员可以提取前 N 个量子比特、后 N 个量子比特,以及从给定索引开始并包含用户指定数量的量子比特的内部切片。

cudaq::qvector 应具有以下结构:

namespace cudaq {
  template <std::size_t Levels = 2>
  class qvector {
    private:
      std::vector<qudit<Levels>> qudits;

    public:
      // 构造一个包含 `size` 个 |0> 态量子比特的量子寄存器
      qvector(std::size_t size);
      qvector(const qvector&) = delete;

      // 迭代器接口
      auto begin();
      auto end();

      // 返回位于 `idx` 的量子比特
      qudit<Levels>& operator[](const std::size_t idx);

      // 返回前 `count` 个量子比特 [0, count)
      qview<Levels> front(std::size_t count);
      // 返回第一个量子比特
      qudit<Levels>& front();
      // 返回后 `count` 个量子比特 [count, size())
      qview<Levels> back(std::size_t count);
      // 返回最后一个量子比特
      qudit<Levels>& back();

      // 返回切片 [start, start+count) 的量子比特
      qview<Levels>
      slice(std::size_t start, std::size_t count);

      // 返回 `{start, start + stride, ...}` 的量子比特
      qview<Levels>
      slice(std::size_t start, std::size_t stride, std::size_t end);

      // 返回包含的量子比特数量
      std::size_t size() const;

      // 销毁所有包含的量子比特。后置条件:`size() == 0`
      void clear();
  };
}

C++ 示例:

cpp

Copy

Download

// 分配 20 个量子比特,类似 std::vector 的语义
cudaq::qvector q(20);
// 获取第一个量子比特
auto first = q.front();
// 获取前 5 个量子比特
auto first_5 = q.front(5);
// 获取最后一个量子比特
auto last = q.back();
// 可以使用 size() 方法循环遍历量子比特
for (int i = 0; i < q.size(); i++) {
  ... 对 q[i] 进行某些操作 ...
}
// 支持基于范围的 for 循环
for (auto & qb : q) {
  ... 对 qb 进行某些操作 ...
}

Python 示例

# Allocate 20 qubits, vector-like semantics
q = cudaq.qvector(20)
# Get the first qubit
first = q.front()
# Get the first 5 qubits
first_5 = q.front(5)
# Get the last qubit
last = q.back()
# Can loop over qubits with size or len function
for i in range(len(q)):
  .. do something with q[i] ..
# Range based for loop
for qb in q:
  .. do something with qb ..

3.3.3. cudaq::qarray<N, Levels = 2>

[1] cudaq::qarray<N, Levels>(其中 N 是整数常量)是一个静态分配的容器(类似于 std::array)。该类型的效用在于编译时已知分配的量子比特容器,这可能直接支持提前进行量子优化和综合。

[2] 第二个模板参数默认为 2 级的 cudaq::qudit

[3] cudaq::qarray 拥有它包含的量子内存,因此不能被复制或移动。

[4] cudaq::qarray 只能在 CUDA-Q 内核中实例化。

[5] cudaq::qarray 中的所有量子比特都从计算基态 |0> 开始。

[6] cudaq::qarray 提供了提取单个量子比特和子寄存器切片的 API。程序员可以提取前 N 个量子比特、后 N 个量子比特,以及从给定索引开始并包含用户指定数量的量子比特的内部切片。

cudaq::qarray 应具有以下结构:

namespace cudaq {
  template <std::size_t N, std::size_t Levels = 2>
  class qarray {
    private:
      std::array<qudit<Levels>, N> qudits;

    public:
      // 构造一个包含 `size` 个 |0> 态量子比特的量子寄存器
      qarray();
      qarray(const qvector&) = delete;
      qarray(qarray &&) = delete;

      qarray& operator=(const qarray &) = delete;

      // 迭代器接口
      auto begin();
      auto end();

      // 返回位于 `idx` 的量子比特
      qudit<Levels>& operator[](const std::size_t idx);

      // 返回前 `count` 个量子比特 [0, count)
      qview<Levels> front(std::size_t count);
      // 返回第一个量子比特
      qudit<Levels>& front();
      // 返回后 `count` 个量子比特 [count, size())
      qview<Levels> back(std::size_t count);
      // 返回最后一个量子比特
      qudit<Levels>& back();

      // 返回切片 [start, start+count) 的量子比特
      qview<Levels>
      slice(std::size_t start, std::size_t count);

      // 返回 `{start, start + stride, ...}` 的量子比特
      qview<Levels>
      slice(std::size_t start, std::size_t stride, std::size_t end);

      // 返回包含的量子比特数量
      std::size_t size() const;

      // 销毁所有包含的量子比特。后置条件:`size() == 0`
      void clear();
  };
}

3.3.4. cudaq::qspan<N, Levels>

(已弃用。请使用 cudaq::qview<Levels> 替代。)

[1] cudaq::qspan 是对离散量子内存空间一部分的非拥有引用,它是一个类似于 std::span 的 C++ 范围,包含 cudaq::qudit(参见 C++ span)。它不拥有其元素。它接受一个模板参数,指示其存储的底层量子比特的级别。对于量子比特,此参数默认为 2。它具有以下结构:

namespace cudaq {
  template <std::size_t Levels = 2>
  class qspan {
    private:
      std::span<qudit<Levels>> qubits;
    public:
      // 构造一个引用 `other` 中量子比特的 span
      qspan(std::ranges::range<qudit<Levels>> auto& other);
      qspan(qspan const& other);

      // 迭代器接口
      auto begin();
      auto end();

      // 返回位于 `idx` 的量子比特
      qudit<Levels>& operator[](const std::size_t idx);

      // 返回前 `count` 个量子比特 [0, count)
      qspan<Levels> front(std::size_t count);
      // 返回第一个量子比特
      qudit<Levels>& front();
      // 返回后 `count` 个量子比特 [count, size())
      qspan<Levels> back(std::size_t count);
      // 返回最后一个量子比特
      qudit<Levels>& back();

      // 返回切片 [start, start+count) 的量子比特
      qspan<Levels>
      slice(std::size_t start, std::size_t count);

      // 返回包含的量子比特数量
      std::size_t size() const;
  };
}

3.3.5. cudaq::qreg<N, Levels>

(已弃用。请使用 cudaq::qvector<Levels> 替代。)

[1] cudaq::qreg<N, Levels> 模拟离散量子内存空间的一个寄存器——一个 cudaq::qudit 的 C++ 容器。作为容器,它拥有其元素及其存储。qreg<dyn, Levels> 是一个动态分配的容器(类似于 std::vector,参见 C++ vector)。cudaq::qreg<N, Levels>(其中 N 是整数常量)是一个静态分配的容器(类似于 std::array,参见 array)。其模板参数默认为动态分配和 cudaq::qudit<2>

namespace cudaq {
  template <std::size_t N = dyn, std::size_t Levels = 2>
  class qreg {
    private:
      std::conditional_t<
        N == dyn,
        std::vector<qudit<Levels>>,
        std::array<qudit<Levels>, N>
      > qudits;
    public:
      // 构造一个包含 `size` 个 |0> 态量子比特的量子寄存器(仅当 N == dyn 时)
      qreg(std::size_t size) requires (N == dyn);
      qreg(qreg const&) = delete;

      // 迭代器接口
      auto begin();
      auto end();

      // 返回位于 `idx` 的量子比特
      qudit<Levels>& operator[](const std::size_t idx);

      // 返回前 `count` 个量子比特 [0, count)
      qspan<dyn, Levels> front(std::size_t count);
      // 返回第一个量子比特
      qudit<Levels>& front();
      // 返回后 `count` 个量子比特 [count, size())
      qspan<dyn, Levels> back(std::size_t count);
      // 返回最后一个量子比特
      qudit<Levels>& back();

      // 返回切片 [start, start+count) 的量子比特
      qspan<dyn, Levels>
      slice(std::size_t start, std::size_t count);

      // 返回包含的量子比特数量
      std::size_t size() const;

      // 销毁所有包含的量子比特。后置条件:`size() == 0`
      void clear();
  };
}

qreg 实例只能从量子内核中实例化,不能在主机代码中实例化。qreg 中的所有量子比特都从计算基态 |0> 开始。

// 分配 20 个量子比特,类似 std::vector 的语义
cudaq::qreg q(20);
auto first = q.front();
auto first_5 = q.front(5);
auto last = q.back();
for (int i = 0; i < q.size(); i++) {
  ... 对 q[i] 进行某些操作 ...
}
for (auto & qb : q) {
  ... 对 qb 进行某些操作 ...
}

// 类似 std::array 的语义
cudaq::qreg<5> fiveCompileTimeQubits;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值