common.title

Docs
Quantum Circuit
TYTAN CLOUD

QUANTUM GAMING


Desktop RAG

Overview
Terms of service

Privacy policy

Contact
Research

Sign in
Sign up
common.title

Tencent Tensor Circuit User Review

Yuichiro Minato

2023/07/11 23:54

Quantum computer simulators are also advancing. This time, we're looking at Tencent's latest tool, a tensor network-based quantum circuit simulator. I've been warning that Japanese domestic technology is falling behind, but I'm tired of looking back, so I'm going to keep chasing the latest!

Tensor networks are attracting attention as an alternative to the conventional state vector method, which uses tensor products of state vectors and quantum gates to calculate while preserving quantum states. Its use has been rapidly increasing in recent years. It works well with NISQ and not so well with FTQC, but FTQC is a story for the future, so it will be utilized for NISQ.

The backends use TensorFlow / PyTorch / JAX, so deep learning-oriented hardware such as CPU/GPU/TPU is used. Let's take a look right away.

github is here

https://github.com/tencent-quantum-lab/tensorcircuit

paper

https://arxiv.org/abs/2205.10091

document

https://tensorcircuit.readthedocs.io/en/latest/

There are plenty of tutorials, and I'll explain them vigorously. For basic information about tensor networks, please refer to the various articles I've published.

Now we look little bit about the paper.

TensorCircuit: a Quantum Software Framework for the NISQ Era

https://quantum-journal.org/papers/q-2023-02-02-912/

Intro

In anticipation of quantum computing becoming more complex and large-scale, a new framework is being built based on tensor networks. It is built on top of frameworks such as TensorFlow, Pytorch, and JAX.

PQC

Variational quantum computations, which introduce parameters, are used in contexts such as VQE/QAOA/QML, making it an optimal framework for these. It calculates the expectation value of the Hamiltonian from the quantum variational principle through optimization of the variational quantum circuits that introduce parameters.

Machine Learning

With the introduction of automatic differentiation, the JIT compiler, VMAP, and hardware-conscious features like the GPU, things have become convenient.

Tensor Network Engine

The engine is built based on standard libraries such as cotengra and Google's tensornetwork, and calculations are actually performed by einsum/matmul.

Tutorials

import tensorcircuit as tc
c = tc.Circuit(2)
c.H(0)
c.CNOT(0,1)
c.rx(1, theta=0.2)
print(c.wavefunction())
print(c.expectation_ps(z=[0, 1]))
print(c.sample(allow_state=True, batch=1024, format="count_dict_bin"))

The quantum circuit is in a general form. The printout below shows the state vector, Hamiltonian expectation value, and then the sampling. I assume there is probably a limit to the maximum number of quantum bits for the state vector.

tf.Tensor(
[0.70357419+0.j 0. -0.07059289j 0. -0.07059289j
0.70357419+0.j ], shape=(4,), dtype=complex128)
tf.Tensor((0.9800665772491607+0j), shape=(), dtype=complex128)
{'00': 533, '01': 2, '10': 3, '11': 486}

There are settings that include the backend.

tc.set_backend("tensorflow")
tc.set_dtype("complex128")
tc.set_contractor("greedy")

Example for automatic differentiation

def forward(theta):
  c = tc.Circuit(2)
  c.R(0, theta=theta, alpha=0.5, phi=0.8)
  return tc.backend.real(c.expectation((tc.gates.z(), [0])))
g = tc.backend.grad(forward)
g = tc.backend.jit(g)
theta = tc.array_to_tensor(1.0)
print(g(theta))

It's convenient. Almost all calculations are included.

I'll try a tutorial. Honestly, the way of writing seems a bit difficult, but since all the necessary functions are available, I'll manage to use it somehow.

QAOA

import tensorcircuit as tc
import tensorflow as tf
import networkx as nx
import matplotlib.pyplot as plt
import numpy as np
from IPython.display import clear_output
import random
K = tc.set_backend("tensorflow")
nlayers = 3 # the number of layers
ncircuits = 6 # six circuits with different initial parameters are going to be optimized at the same time
nnodes = 8 # the number of nodes

It seems like it's computing and comparing circuits with three layers (p=3) and six instances simultaneously. If the node count is 8, it seems like the number of quantum bits will be 8.

Problem Setup

The problem is being set up using a graph.

# a graph instance
each node is connected to three nodes
for example, node 0 is connected to nodes 1,7,3
example_graph_dict = {
  0: {1: {"weight": 1.0}, 7: {"weight": 1.0}, 3: {"weight": 1.0}},
  1: {0: {"weight": 1.0}, 2: {"weight": 1.0}, 3: {"weight": 1.0}},
  2: {1: {"weight": 1.0}, 3: {"weight": 1.0}, 5: {"weight": 1.0}},
  3: {1: {"weight": 1.0}, 2: {"weight": 1.0}, 0: {"weight": 1.0}},
  4: {7: {"weight": 1.0}, 6: {"weight": 1.0}, 5: {"weight": 1.0}},
  5: {6: {"weight": 1.0}, 4: {"weight": 1.0}, 2: {"weight": 1.0}},
  6: {7: {"weight": 1.0}, 4: {"weight": 1.0}, 5: {"weight": 1.0}},
  7: {4: {"weight": 1.0}, 6: {"weight": 1.0}, 0: {"weight": 1.0}},
}
pos = nx.spring_layout(nx.to_networkx_graph(example_graph_dict))
colors = ["c" for key in example_graph_dict.items()]
convert to a NetworkX graph
example_graph = nx.to_networkx_graph(example_graph_dict)
nx.draw_networkx(example_graph, with_labels=True, node_color=colors, pos=pos)
ax = plt.gca()
ax.set_facecolor("w")

Ansatz for QAOA

def QAOAansatz(params, g=example_graph, return_circuit=False):
  n = len(g.nodes) # the number of nodes
  c = tc.Circuit(n)
  for i in range(n): #initial state for mixer X is |+>
    c.H(i)
  # PQC
  for j in range(nlayers):
    # U_j
    for e in g.edges:
      c.exp1(
        e[0],
        e[1],
        unitary=tc.gates._zz_matrix,
        theta=g[e[0]][e[1]].get("weight", 1.0) * params[2 * j],
      ) #setting ZZ for each edge, as it is maxcut problem no bias(local magnetic field)
    # V_j
    for i in range(n):
      c.rx(i, theta=params[2 * j + 1]) # time evolution of X hamitonian of TFIM
  # whether to return the circuit
  if return_circuit is True:
    return c
  # calculate the loss function
  loss = 0.0
  for e in g.edges:
    loss += c.expectation_ps(z=[e[0], e[1]]) * g[e[0]][e[1]].get("weight", 1.0) #expectation value of hamiltonian
  return K.real(loss)

The implementation feels quite meticulous. It seems tough to implement the time evolution operator for QAOA without prior knowledge. But it seems feasible for someone who knows it.

# use vvag to get the losses and gradients with different random circuit instances
QAOA_vvag = K.jit(
  tc.backend.vvag(QAOAansatz, argnums=0, vectorized_argnums=0), static_argnums=(1, 2)
)

params = K.implicit_randn(
  shape=[ncircuits, 2 * nlayers], stddev=0.1
) # initial parameters
opt = K.optimizer(tf.keras.optimizers.Adam(1e-2))
list_of_loss = [[] for i in range(ncircuits)]
for i in range(300):
  loss, grads = QAOA_vvag(params, example_graph)
  params = opt.update(grads, params) # gradient descent
  # visualise the progress
  clear_output(wait=True)
  list_of_loss = np.hstack((list_of_loss, K.numpy(loss)[:, np.newaxis]))
  plt.xlabel("Iteration")
  plt.ylabel("Cost")
  for index in range(ncircuits):
    plt.plot(range(i + 1), list_of_loss[index])
  legend = ["circuit %d" % leg for leg in range(ncircuits)]
  plt.legend(legend)
  plt.show()

Implementation seems to require a good deal of knowledge.

The number of parameters is set to twice the three layers for six circuits.

The optimization solver is Adam.

After that, it simply calculates the expectation value. There doesn't seem to be any special computations.

It appears to be taking the maximum probability from the amplitude with something like a state vector. The calculation of each expectation value differs, but the answers from the maximum amplitude (or sampling) seem to be the same.

# print all results
for num_circuit in range(ncircuits):
  c = QAOAansatz(params=params[num_circuit], g=example_graph, return_circuit=True)
  loss = QAOAansatz(params=params[num_circuit], g=example_graph)
  # find the states with max probabilities
  probs = K.numpy(c.probability()).round(decimals=4)
  index = np.where(probs == max(probs))[0]
  states = []
  for i in index:
    states.append(f"{bin(i)[2:]:0>{c._nqubits}}")
  print("Circuit #%d" % num_circuit)
  print("cost:", K.numpy(loss), "\nbit strings:", states, "\n")

This time we looked at Tencent's Tensor Circuit. It seemed like you couldn't create it without a good deal of knowledge, so I thought it might be for people with intermediate or higher skills. I wonder if it will get easier. However, it seemed convenient because it seemed likely that you could calculate quickly with a GPU using a quantum circuit.

That's all.

© 2025, blueqat Inc. All rights reserved