电路基础#

概述#

在这篇笔记中,我们将了解 TensorCircuit 中核心对象的基本操作-tc.Circuit,它支持无噪声仿真和基于蒙特卡洛轨迹的噪声仿真。更重要的是,几乎所有对 Circuit 对象的操作都是可微分的和可即时编译的,这是成功高效地进行变分量子算法模拟的关键。 [WIP note]

设置#

[1]:
from functools import partial
import inspect
import sys
import numpy as np
import tensorflow as tf

import tensorcircuit as tc

“Hello World" 样例#

[2]:
def get_circuit(n):
    c = tc.Circuit(n)  # 用 n 个量子比特初始化一个电路对象
    for i in range(n):
        c.H(i)  # 在每个量子比特上使用 Hadamard 门
    c.cnot(0, 1)  # 在第 0 个量子比特上应用带有控制量子比特的 cnot 门
    c.CNOT(n - 1, n - 2)  # 大写的 API 也可以正常使用
    return c
[3]:
# 打印不含参数的有可能的门
print(tc.Circuit.sgates)
['i', 'x', 'y', 'z', 'h', 't', 's', 'td', 'sd', 'wroot', 'cnot', 'cz', 'swap', 'cy', 'iswap', 'ox', 'oy', 'oz', 'toffoli', 'fredkin']
[4]:
# 这些门定义的相应矩阵
for g in tc.Circuit.sgates:
    gf = getattr(tc.gates, g)
    print(g)
    print(tc.gates.matrix_for_gate(gf()))
i
[[1.+0.j 0.+0.j]
 [0.+0.j 1.+0.j]]
x
[[0.+0.j 1.+0.j]
 [1.+0.j 0.+0.j]]
y
[[0.+0.j 0.-1.j]
 [0.+1.j 0.+0.j]]
z
[[ 1.+0.j  0.+0.j]
 [ 0.+0.j -1.+0.j]]
h
[[ 0.70710677+0.j  0.70710677+0.j]
 [ 0.70710677+0.j -0.70710677+0.j]]
t
[[1.        +0.j         0.        +0.j        ]
 [0.        +0.j         0.70710677+0.70710677j]]
s
[[1.+0.j 0.+0.j]
 [0.+0.j 0.+1.j]]
td
[[1.        +0.j         0.        +0.j        ]
 [0.        +0.j         0.70710677-0.70710677j]]
sd
[[1.+0.j 0.+0.j]
 [0.+0.j 0.-1.j]]
wroot
[[ 0.70710677+0.j  -0.5       -0.5j]
 [ 0.5       -0.5j  0.70710677+0.j ]]
cnot
[[1.+0.j 0.+0.j 0.+0.j 0.+0.j]
 [0.+0.j 1.+0.j 0.+0.j 0.+0.j]
 [0.+0.j 0.+0.j 0.+0.j 1.+0.j]
 [0.+0.j 0.+0.j 1.+0.j 0.+0.j]]
cz
[[ 1.+0.j  0.+0.j  0.+0.j  0.+0.j]
 [ 0.+0.j  1.+0.j  0.+0.j  0.+0.j]
 [ 0.+0.j  0.+0.j  1.+0.j  0.+0.j]
 [ 0.+0.j  0.+0.j  0.+0.j -1.+0.j]]
swap
[[1.+0.j 0.+0.j 0.+0.j 0.+0.j]
 [0.+0.j 0.+0.j 1.+0.j 0.+0.j]
 [0.+0.j 1.+0.j 0.+0.j 0.+0.j]
 [0.+0.j 0.+0.j 0.+0.j 1.+0.j]]
cy
[[1.+0.j 0.+0.j 0.+0.j 0.+0.j]
 [0.+0.j 1.+0.j 0.+0.j 0.+0.j]
 [0.+0.j 0.+0.j 0.+0.j 0.-1.j]
 [0.+0.j 0.+0.j 0.+1.j 0.+0.j]]
iswap
[[1.+0.j 0.+0.j 0.+0.j 0.+0.j]
 [0.+0.j 0.+0.j 0.+1.j 0.+0.j]
 [0.+0.j 0.+1.j 0.+0.j 0.+0.j]
 [0.+0.j 0.+0.j 0.+0.j 1.+0.j]]
ox
[[0.+0.j 1.+0.j 0.+0.j 0.+0.j]
 [1.+0.j 0.+0.j 0.+0.j 0.+0.j]
 [0.+0.j 0.+0.j 1.+0.j 0.+0.j]
 [0.+0.j 0.+0.j 0.+0.j 1.+0.j]]
oy
[[0.+0.j 0.-1.j 0.+0.j 0.+0.j]
 [0.+1.j 0.+0.j 0.+0.j 0.+0.j]
 [0.+0.j 0.+0.j 1.+0.j 0.+0.j]
 [0.+0.j 0.+0.j 0.+0.j 1.+0.j]]
oz
[[ 1.+0.j  0.+0.j  0.+0.j  0.+0.j]
 [ 0.+0.j -1.+0.j  0.+0.j  0.+0.j]
 [ 0.+0.j  0.+0.j  1.+0.j  0.+0.j]
 [ 0.+0.j  0.+0.j  0.+0.j  1.+0.j]]
toffoli
[[1.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j]
 [0.+0.j 1.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j]
 [0.+0.j 0.+0.j 1.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j]
 [0.+0.j 0.+0.j 0.+0.j 1.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j]
 [0.+0.j 0.+0.j 0.+0.j 0.+0.j 1.+0.j 0.+0.j 0.+0.j 0.+0.j]
 [0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 1.+0.j 0.+0.j 0.+0.j]
 [0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 1.+0.j]
 [0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 1.+0.j 0.+0.j]]
fredkin
[[1.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j]
 [0.+0.j 1.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j]
 [0.+0.j 0.+0.j 1.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j]
 [0.+0.j 0.+0.j 0.+0.j 1.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j]
 [0.+0.j 0.+0.j 0.+0.j 0.+0.j 1.+0.j 0.+0.j 0.+0.j 0.+0.j]
 [0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 1.+0.j 0.+0.j]
 [0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 1.+0.j 0.+0.j 0.+0.j]
 [0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 1.+0.j]]
[5]:
c = get_circuit(3)
ir = c.to_qir()  # 电路的中间表示
ir
[5]:
[{'gatef': h,
  'gate': Gate(
      name: 'h',
      tensor:
          array([[ 0.70710677+0.j,  0.70710677+0.j],
                 [ 0.70710677+0.j, -0.70710677+0.j]], dtype=complex64),
      edges: [
          Edge('cnot'[2] -> 'h'[0] ),
          Edge('h'[1] -> 'qb-1'[0] )
      ]),
  'index': (0,),
  'name': 'h',
  'split': None,
  'mpo': False},
 {'gatef': h,
  'gate': Gate(
      name: 'h',
      tensor:
          array([[ 0.70710677+0.j,  0.70710677+0.j],
                 [ 0.70710677+0.j, -0.70710677+0.j]], dtype=complex64),
      edges: [
          Edge('cnot'[3] -> 'h'[0] ),
          Edge('h'[1] -> 'qb-2'[0] )
      ]),
  'index': (1,),
  'name': 'h',
  'split': None,
  'mpo': False},
 {'gatef': h,
  'gate': Gate(
      name: 'h',
      tensor:
          array([[ 0.70710677+0.j,  0.70710677+0.j],
                 [ 0.70710677+0.j, -0.70710677+0.j]], dtype=complex64),
      edges: [
          Edge('cnot'[2] -> 'h'[0] ),
          Edge('h'[1] -> 'qb-3'[0] )
      ]),
  'index': (2,),
  'name': 'h',
  'split': None,
  'mpo': False},
 {'gatef': cnot,
  'gate': Gate(
      name: 'cnot',
      tensor:
          array([[[[1.+0.j, 0.+0.j],
                   [0.+0.j, 0.+0.j]],

                  [[0.+0.j, 1.+0.j],
                   [0.+0.j, 0.+0.j]]],


                 [[[0.+0.j, 0.+0.j],
                   [0.+0.j, 1.+0.j]],

                  [[0.+0.j, 0.+0.j],
                   [1.+0.j, 0.+0.j]]]], dtype=complex64),
      edges: [
          Edge(Dangling Edge)[0],
          Edge('cnot'[3] -> 'cnot'[1] ),
          Edge('cnot'[2] -> 'h'[0] ),
          Edge('cnot'[3] -> 'h'[0] )
      ]),
  'index': (0, 1),
  'name': 'cnot',
  'split': None,
  'mpo': False},
 {'gatef': cnot,
  'gate': Gate(
      name: 'cnot',
      tensor:
          array([[[[1.+0.j, 0.+0.j],
                   [0.+0.j, 0.+0.j]],

                  [[0.+0.j, 1.+0.j],
                   [0.+0.j, 0.+0.j]]],


                 [[[0.+0.j, 0.+0.j],
                   [0.+0.j, 1.+0.j]],

                  [[0.+0.j, 0.+0.j],
                   [1.+0.j, 0.+0.j]]]], dtype=complex64),
      edges: [
          Edge(Dangling Edge)[0],
          Edge(Dangling Edge)[1],
          Edge('cnot'[2] -> 'h'[0] ),
          Edge('cnot'[3] -> 'cnot'[1] )
      ]),
  'index': (2, 1),
  'name': 'cnot',
  'split': None,
  'mpo': False}]
[6]:
ir[0]["gatef"]().tensor, ir[-1]["gate"].tensor  # 每个门的实际幺正矩阵
[6]:
(array([[ 0.70710677+0.j,  0.70710677+0.j],
        [ 0.70710677+0.j, -0.70710677+0.j]], dtype=complex64),
 array([[[[1.+0.j, 0.+0.j],
          [0.+0.j, 0.+0.j]],

         [[0.+0.j, 1.+0.j],
          [0.+0.j, 0.+0.j]]],


        [[[0.+0.j, 0.+0.j],
          [0.+0.j, 1.+0.j]],

         [[0.+0.j, 0.+0.j],
          [1.+0.j, 0.+0.j]]]], dtype=complex64))
[7]:
# 计算电路的最终输出量子态
c.state()
[7]:
array([0.35355335+0.j, 0.35355335+0.j, 0.35355335+0.j, 0.35355335+0.j,
       0.35355335+0.j, 0.35355335+0.j, 0.35355335+0.j, 0.35355335+0.j],
      dtype=complex64)
[8]:
# 计算一些期望值,比如 <X1>
x1 = c.expectation([tc.gates.x(), [1]])

# 或 <Z1Z2>
z1z2 = c.expectation([tc.gates.z(), [1]], [tc.gates.z(), [2]])

print(x1, z1z2)
(0.9999998+0j) 0j
[9]:
# 做一些随机取样
for _ in range(10):
    print(c.perfect_sampling())
(array([1., 1., 1.], dtype=float32), 0.1250001713634208)
(array([0., 0., 1.], dtype=float32), 0.12499997764825821)
(array([0., 1., 1.], dtype=float32), 0.12499997764825821)
(array([1., 1., 0.], dtype=float32), 0.1249999776482098)
(array([1., 1., 0.], dtype=float32), 0.1249999776482098)
(array([1., 0., 1.], dtype=float32), 0.12499997019766829)
(array([0., 1., 0.], dtype=float32), 0.12499997764825821)
(array([1., 1., 0.], dtype=float32), 0.1249999776482098)
(array([0., 0., 0.], dtype=float32), 0.12499997764825821)
(array([0., 1., 1.], dtype=float32), 0.12499997764825821)
[10]:
# 我们可以轻松地从 NumPy 切换模拟后端!

with tc.runtime_backend("tensorflow") as K:
    c = get_circuit(3)
    print(c.state())

with tc.runtime_backend("jax") as K:
    c = get_circuit(3)
    print(c.state())

with tc.runtime_backend("pytorch") as K:
    # pytorch 后端无法保证最佳性能和完整功能
    c = get_circuit(3)
    print(c.state())
tf.Tensor(
[0.35355335+0.j 0.35355335+0.j 0.35355335+0.j 0.35355335+0.j
 0.35355335+0.j 0.35355335+0.j 0.35355335+0.j 0.35355335+0.j], shape=(8,), dtype=complex64)
WARNING:absl:No GPU/TPU found, falling back to CPU. (Set TF_CPP_MIN_LOG_LEVEL=0 and rerun for more info.)
[0.35355335+0.j 0.35355335+0.j 0.35355335+0.j 0.35355335+0.j
 0.35355335+0.j 0.35355335+0.j 0.35355335+0.j 0.35355335+0.j]
tensor([0.3536+0.j, 0.3536+0.j, 0.3536+0.j, 0.3536+0.j, 0.3536+0.j, 0.3536+0.j, 0.3536+0.j,
        0.3536+0.j])

参数化量子电路(PQC)#

[11]:
# 接受参数的量子电路门

print(tc.Circuit.vgates)
['r', 'cr', 'rx', 'ry', 'rz', 'crx', 'cry', 'crz', 'orx', 'ory', 'orz', 'any', 'exp', 'exp1']
[12]:
# 查看每种类型的变量门的关键字参数(类型为浮点数)
for g in tc.Circuit.vgates:
    print(g, inspect.signature(getattr(tc.gates, g).f))
r (theta: float = 0, alpha: float = 0, phi: float = 0) -> tensorcircuit.gates.Gate
cr (theta: float = 0, alpha: float = 0, phi: float = 0) -> tensorcircuit.gates.Gate
rx (theta: float = 0) -> tensorcircuit.gates.Gate
ry (theta: float = 0) -> tensorcircuit.gates.Gate
rz (theta: float = 0) -> tensorcircuit.gates.Gate
crx (*args: Any, **kws: Any) -> Any
cry (*args: Any, **kws: Any) -> Any
crz (*args: Any, **kws: Any) -> Any
orx (*args: Any, **kws: Any) -> Any
ory (*args: Any, **kws: Any) -> Any
orz (*args: Any, **kws: Any) -> Any
any (unitary: Any, name: str = 'any') -> tensorcircuit.gates.Gate
exp (unitary: Any, theta: float, name: str = 'none') -> tensorcircuit.gates.Gate
exp1 (unitary: Any, theta: float, name: str = 'none') -> tensorcircuit.gates.Gate
[13]:
def get_circuit(n, params):
    c = tc.Circuit(n)  # 用 n 个量子比特初始化一个电路对象
    for i in range(n):
        c.rx(i, theta=params[i])  # 应用 rx 门
    c.cnot(0, 1)
    return c
[14]:
K = tc.set_backend("tensorflow")
[15]:
n = 3
params = K.ones([n])
c = get_circuit(n, params)
print(c.state())
tf.Tensor(
[ 0.6758712 +0.j          0.        -0.36923012j  0.        -0.36923015j
 -0.20171136-0.j         -0.20171136+0.j          0.        +0.11019541j
  0.        -0.36923015j -0.20171136-0.j        ], shape=(8,), dtype=complex64)
[16]:
ir = c.to_qir()
ir
[16]:
[{'gatef': rx,
  'index': (0,),
  'name': 'rx',
  'split': None,
  'mpo': False,
  'parameters': {'theta': <tf.Tensor: shape=(), dtype=complex64, numpy=(1+0j)>},
  'gate': Gate(
      name: '__unnamed_node__',
      tensor:
          <tf.Tensor: shape=(2, 2), dtype=complex64, numpy=
          array([[0.87758255+0.j        , 0.        -0.47942555j],
                 [0.        -0.47942555j, 0.87758255+0.j        ]], dtype=complex64)>,
      edges: [
          Edge('cnot'[2] -> '__unnamed_node__'[0] ),
          Edge('__unnamed_node__'[1] -> 'qb-1'[0] )
      ])},
 {'gatef': rx,
  'index': (1,),
  'name': 'rx',
  'split': None,
  'mpo': False,
  'parameters': {'theta': <tf.Tensor: shape=(), dtype=complex64, numpy=(1+0j)>},
  'gate': Gate(
      name: '__unnamed_node__',
      tensor:
          <tf.Tensor: shape=(2, 2), dtype=complex64, numpy=
          array([[0.87758255+0.j        , 0.        -0.47942555j],
                 [0.        -0.47942555j, 0.87758255+0.j        ]], dtype=complex64)>,
      edges: [
          Edge('cnot'[3] -> '__unnamed_node__'[0] ),
          Edge('__unnamed_node__'[1] -> 'qb-2'[0] )
      ])},
 {'gatef': rx,
  'index': (2,),
  'name': 'rx',
  'split': None,
  'mpo': False,
  'parameters': {'theta': <tf.Tensor: shape=(), dtype=complex64, numpy=(1+0j)>},
  'gate': Gate(
      name: '__unnamed_node__',
      tensor:
          <tf.Tensor: shape=(2, 2), dtype=complex64, numpy=
          array([[0.87758255+0.j        , 0.        -0.47942555j],
                 [0.        -0.47942555j, 0.87758255+0.j        ]], dtype=complex64)>,
      edges: [
          Edge(Dangling Edge)[0],
          Edge('__unnamed_node__'[1] -> 'qb-3'[0] )
      ])},
 {'gatef': cnot,
  'gate': Gate(
      name: 'cnot',
      tensor:
          <tf.Tensor: shape=(2, 2, 2, 2), dtype=complex64, numpy=
          array([[[[1.+0.j, 0.+0.j],
                   [0.+0.j, 0.+0.j]],

                  [[0.+0.j, 1.+0.j],
                   [0.+0.j, 0.+0.j]]],


                 [[[0.+0.j, 0.+0.j],
                   [0.+0.j, 1.+0.j]],

                  [[0.+0.j, 0.+0.j],
                   [1.+0.j, 0.+0.j]]]], dtype=complex64)>,
      edges: [
          Edge(Dangling Edge)[0],
          Edge(Dangling Edge)[1],
          Edge('cnot'[2] -> '__unnamed_node__'[0] ),
          Edge('cnot'[3] -> '__unnamed_node__'[0] )
      ]),
  'index': (0, 1),
  'name': 'cnot',
  'split': None,
  'mpo': False}]
[17]:
# 查看量子门对应的矩阵
ir[0]["gatef"](**ir[0]["parameters"]).tensor
[17]:
<tf.Tensor: shape=(2, 2), dtype=complex64, numpy=
array([[0.87758255+0.j        , 0.        -0.47942555j],
       [0.        -0.47942555j, 0.87758255+0.j        ]], dtype=complex64)>
[18]:
# 让我们组成一个可微分的量子函数


def energy(params):
    c = get_circuit(n, params)
    return K.real(c.expectation([tc.gates.z(), [1]]))


energy_vag = K.value_and_grad(energy)

print(energy_vag(params))

# 一旦我们有了梯度,我们就可以运行基于梯度的下降的变分优化
(<tf.Tensor: shape=(), dtype=float32, numpy=0.2919265>, <tf.Tensor: shape=(3,), dtype=complex64, numpy=
array([-4.5464873e-01+0.j, -4.5464873e-01+0.j,  2.2351742e-08+0.j],
      dtype=complex64)>)
[19]:
# 并且使其可即时编译以加速

energy_vag_jit = K.jit(K.value_and_grad(energy))

print(energy_vag_jit(params))
# 第一次运行可即时编译的函数会很慢,但是后面的测量会超级快
(<tf.Tensor: shape=(), dtype=float32, numpy=0.2919265>, <tf.Tensor: shape=(3,), dtype=complex64, numpy=
array([-4.5464873e-01+0.j, -4.5464873e-01+0.j,  2.2351742e-08+0.j],
      dtype=complex64)>)

电路的高级用法#

输入状态#

我们可以从默认的 |0^n> 替换输入状态

[20]:
input_state = K.ones([2**n])
input_state /= K.norm(input_state)

c = tc.Circuit(n, inputs=input_state)
c.H(0)
c.state()
[20]:
<tf.Tensor: shape=(8,), dtype=complex64, numpy=
array([0.49999997+0.j, 0.49999997+0.j, 0.49999997+0.j, 0.49999997+0.j,
       0.        +0.j, 0.        +0.j, 0.        +0.j, 0.        +0.j],
      dtype=complex64)>

蒙特卡罗方法噪声模拟#

tc.Circuit 支持使用蒙特卡罗方法进行噪声模拟,并且它也是可即时编译的! 此外,tc.DMCircuit 支持使用全密度矩阵方法进行噪声模拟。

[21]:
c = tc.Circuit(n)
for i in range(n):
    c.H(i)
for i in range(n - 1):
    c.cnot(i, i + 1)
    c.depolarizing(i, px=0.1, py=0.1, pz=0.1)
    c.apply_general_kraus(tc.channels.phasedampingchannel(gamma=0.2), i + 1)
print(c.expectation([tc.gates.y(), [1]]))
tf.Tensor(0j, shape=(), dtype=complex64)

应用任意幺正门#

只需直接使用 any API 通过提供相应的幺正矩阵

[22]:
c = tc.Circuit(n)
c.any(0, 1, unitary=K.ones([4, 4]) / K.norm(K.ones([4, 4])))
c.state()
[22]:
<tf.Tensor: shape=(8,), dtype=complex64, numpy=
array([0.25+0.j, 0.  +0.j, 0.25+0.j, 0.  +0.j, 0.25+0.j, 0.  +0.j,
       0.25+0.j, 0.  +0.j], dtype=complex64)>

指数门#

如果我们想将门模拟为 \(e^{i\theta G}\) ,其中 \(G^2=1\) 是一个矩阵,我们有一个快速有效的门实现,例如 exp1

[23]:
c = tc.Circuit(n)
for i in range(n):
    c.H(i)
for i in range(n - 1):
    c.exp1(i, i + 1, theta=K.ones([]), unitary=tc.gates._zz_matrix)
c.state()
[23]:
<tf.Tensor: shape=(8,), dtype=complex64, numpy=
array([-0.14713009-3.2148516e-01j,  0.35355335+1.4901161e-08j,
       -0.14713009+3.2148516e-01j,  0.35355335-1.4901161e-08j,
        0.35355335-1.4901161e-08j, -0.14713009+3.2148516e-01j,
        0.35355335+1.4901161e-08j, -0.14713009-3.2148516e-01j],
      dtype=complex64)>

在上面的例子中 \(G=Z\otimes Z\)

[24]:
print(tc.gates._zz_matrix)
[[ 1.  0.  0.  0.]
 [ 0. -1.  0. -0.]
 [ 0.  0. -1. -0.]
 [ 0. -0. -0.  1.]]

下面列出了门模块中的常用矩阵

[25]:
for name in dir(tc.gates):
    if name.endswith("_matrix"):
        print(name, ":\n", getattr(tc.gates, name))
_cnot_matrix :
 [[1. 0. 0. 0.]
 [0. 1. 0. 0.]
 [0. 0. 0. 1.]
 [0. 0. 1. 0.]]
_cy_matrix :
 [[ 1.+0.j  0.+0.j  0.+0.j  0.+0.j]
 [ 0.+0.j  1.+0.j  0.+0.j  0.+0.j]
 [ 0.+0.j  0.+0.j  0.+0.j -0.-1.j]
 [ 0.+0.j  0.+0.j  0.+1.j  0.+0.j]]
_cz_matrix :
 [[ 1.  0.  0.  0.]
 [ 0.  1.  0.  0.]
 [ 0.  0.  1.  0.]
 [ 0.  0.  0. -1.]]
_fredkin_matrix :
 [[1. 0. 0. 0. 0. 0. 0. 0.]
 [0. 1. 0. 0. 0. 0. 0. 0.]
 [0. 0. 1. 0. 0. 0. 0. 0.]
 [0. 0. 0. 1. 0. 0. 0. 0.]
 [0. 0. 0. 0. 1. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 1. 0.]
 [0. 0. 0. 0. 0. 1. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 1.]]
_h_matrix :
 [[ 0.70710678  0.70710678]
 [ 0.70710678 -0.70710678]]
_i_matrix :
 [[1. 0.]
 [0. 1.]]
_ii_matrix :
 [[1. 0. 0. 0.]
 [0. 1. 0. 0.]
 [0. 0. 1. 0.]
 [0. 0. 0. 1.]]
_s_matrix :
 [[1.+0.j 0.+0.j]
 [0.+0.j 0.+1.j]]
_swap_matrix :
 [[1. 0. 0. 0.]
 [0. 0. 1. 0.]
 [0. 1. 0. 0.]
 [0. 0. 0. 1.]]
_t_matrix :
 [[1.        +0.j         0.        +0.j        ]
 [0.        +0.j         0.70710678+0.70710678j]]
_toffoli_matrix :
 [[1. 0. 0. 0. 0. 0. 0. 0.]
 [0. 1. 0. 0. 0. 0. 0. 0.]
 [0. 0. 1. 0. 0. 0. 0. 0.]
 [0. 0. 0. 1. 0. 0. 0. 0.]
 [0. 0. 0. 0. 1. 0. 0. 0.]
 [0. 0. 0. 0. 0. 1. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 1.]
 [0. 0. 0. 0. 0. 0. 1. 0.]]
_wroot_matrix :
 [[ 0.70710678+0.j  -0.5       -0.5j]
 [ 0.5       -0.5j  0.70710678+0.j ]]
_x_matrix :
 [[0. 1.]
 [1. 0.]]
_xx_matrix :
 [[0. 0. 0. 1.]
 [0. 0. 1. 0.]
 [0. 1. 0. 0.]
 [1. 0. 0. 0.]]
_y_matrix :
 [[ 0.+0.j -0.-1.j]
 [ 0.+1.j  0.+0.j]]
_yy_matrix :
 [[ 0.+0.j  0.-0.j  0.-0.j -1.+0.j]
 [ 0.+0.j  0.+0.j  1.-0.j  0.-0.j]
 [ 0.+0.j  1.-0.j  0.+0.j  0.-0.j]
 [-1.+0.j  0.+0.j  0.+0.j  0.+0.j]]
_z_matrix :
 [[ 1.  0.]
 [ 0. -1.]]
_zz_matrix :
 [[ 1.  0.  0.  0.]
 [ 0. -1.  0. -0.]
 [ 0.  0. -1. -0.]
 [ 0. -0. -0.  1.]]

非幺正门#

tc.Circuit由于其张量网络引擎性质而自动支持非幺正电路仿真

[26]:
c = tc.Circuit(n)
c.exp1(1, unitary=tc.gates._x_matrix, theta=K.ones([]) + 1.0j * K.ones([]))
c.state()
[26]:
<tf.Tensor: shape=(8,), dtype=complex64, numpy=
array([0.83373   -0.9888977j, 0.        +0.j       ,
       0.63496387-1.2984576j, 0.        +0.j       ,
       0.        +0.j       , 0.        +0.j       ,
       0.        +0.j       , 0.        +0.j       ], dtype=complex64)>

请注意,在这种情况下,最终量子态不再归一化。

[27]:
try:
    np.testing.assert_allclose(K.norm(c.state()), 1.0)
except AssertionError as e:
    print(e)

Not equal to tolerance rtol=1e-07, atol=0

Mismatched elements: 1 / 1 (100%)
Max absolute difference: 0.93963802
Max relative difference: 0.93963802
 x: array(1.939638+0.j, dtype=complex64)
 y: array(1.)