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;
20万+

被折叠的 条评论
为什么被折叠?



