tensorcircuit.quantum#

Quantum state and operator class backend by tensornetwork

IMPORT

import tensorcircuit.quantum as qu
tensorcircuit.quantum.PauliString2COO(l: Sequence[int], weight: Optional[float] = None) β†’ Any[source]#

Generate tensorflow sparse matrix from Pauli string sum

Parameters
  • l (Sequence[int]) – 1D Tensor representing for a Pauli string, e.g. [1, 0, 0, 3, 2] is for \(X_0Z_3Y_4\)

  • weight (Optional[float], optional) – the weight for the Pauli string defaults to None (all Pauli strings weight 1.0)

Returns

the tensorflow sparse matrix

Return type

Tensor

tensorcircuit.quantum.PauliStringSum2COO(ls: Sequence[Sequence[int]], weight: Optional[Sequence[float]] = None, numpy: bool = False) β†’ Any[source]#

Generate sparse tensor from Pauli string sum. Currently requires tensorflow installed

Parameters
  • ls (Sequence[Sequence[int]]) – 2D Tensor, each row is for a Pauli string, e.g. [1, 0, 0, 3, 2] is for \(X_0Z_3Y_4\)

  • weight (Optional[Sequence[float]], optional) – 1D Tensor, each element corresponds the weight for each Pauli string defaults to None (all Pauli strings weight 1.0)

  • numpy (bool) – default False. If True, return numpy coo else return backend compatible sparse tensor

Returns

the scipy coo sparse matrix

Return type

Tensor

tensorcircuit.quantum.PauliStringSum2COO_numpy(ls: Sequence[Sequence[int]], weight: Optional[Sequence[float]] = None, *, numpy: bool = True) β†’ Any#

Generate sparse tensor from Pauli string sum. Currently requires tensorflow installed

Parameters
  • ls (Sequence[Sequence[int]]) – 2D Tensor, each row is for a Pauli string, e.g. [1, 0, 0, 3, 2] is for \(X_0Z_3Y_4\)

  • weight (Optional[Sequence[float]], optional) – 1D Tensor, each element corresponds the weight for each Pauli string defaults to None (all Pauli strings weight 1.0)

  • numpy (bool) – default False. If True, return numpy coo else return backend compatible sparse tensor

Returns

the scipy coo sparse matrix

Return type

Tensor

tensorcircuit.quantum.PauliStringSum2COO_tf(ls: Sequence[Sequence[int]], weight: Optional[Sequence[float]] = None) β†’ Any[source]#

Generate tensorflow sparse matrix from Pauli string sum

Parameters
  • ls (Sequence[Sequence[int]]) – 2D Tensor, each row is for a Pauli string, e.g. [1, 0, 0, 3, 2] is for \(X_0Z_3Y_4\)

  • weight (Optional[Sequence[float]], optional) – 1D Tensor, each element corresponds the weight for each Pauli string defaults to None (all Pauli strings weight 1.0)

Returns

the tensorflow coo sparse matrix

Return type

Tensor

tensorcircuit.quantum.PauliStringSum2Dense(ls: Sequence[Sequence[int]], weight: Optional[Sequence[float]] = None, numpy: bool = False) β†’ Any[source]#

Generate dense matrix from Pauli string sum. Currently requires tensorflow installed.

Parameters
  • ls (Sequence[Sequence[int]]) – 2D Tensor, each row is for a Pauli string, e.g. [1, 0, 0, 3, 2] is for \(X_0Z_3Y_4\)

  • weight (Optional[Sequence[float]], optional) – 1D Tensor, each element corresponds the weight for each Pauli string defaults to None (all Pauli strings weight 1.0)

  • numpy (bool) – default False. If True, return numpy coo else return backend compatible sparse tensor

Returns

the tensorflow dense matrix

Return type

Tensor

class tensorcircuit.quantum.QuAdjointVector(subsystem_edges: Sequence[tensornetwork.network_components.Edge], ref_nodes: Optional[Collection[tensornetwork.network_components.AbstractNode]] = None, ignore_edges: Optional[Collection[tensornetwork.network_components.Edge]] = None)[source]#

Bases: tensorcircuit.quantum.QuOperator

Represents an adjoint (row) vector via a tensor network.

__init__(subsystem_edges: Sequence[tensornetwork.network_components.Edge], ref_nodes: Optional[Collection[tensornetwork.network_components.AbstractNode]] = None, ignore_edges: Optional[Collection[tensornetwork.network_components.Edge]] = None) β†’ None[source]#

Constructs a new QuAdjointVector from a tensor network. This encapsulates an existing tensor network, interpreting it as an adjoint vector (row vector).

Parameters
  • subsystem_edges (Sequence[Edge]) – The edges of the network to be used as the input edges.

  • ref_nodes (Optional[Collection[AbstractNode]], optional) – Nodes used to refer to parts of the tensor network that are not connected to any input or output edges (for example: a scalar factor).

  • ignore_edges (Optional[Collection[Edge]], optional) – Optional collection of edges to ignore when performing consistency checks.

adjoint() β†’ tensorcircuit.quantum.QuOperator#

The adjoint of the operator. This creates a new QuOperator with complex-conjugate copies of all tensors in the network and with the input and output edges switched.

Returns

The adjoint of the operator.

Return type

QuOperator

check_network() β†’ None#

Check that the network has the expected dimensionality. This checks that all input and output edges are dangling and that there are no other dangling edges (except any specified in ignore_edges). If not, an exception is raised.

contract(final_edge_order: Optional[Sequence[tensornetwork.network_components.Edge]] = None) β†’ tensorcircuit.quantum.QuOperator#

Contract the tensor network in place. This modifies the tensor network representation of the operator (or vector, or scalar), reducing it to a single tensor, without changing the value.

Parameters

final_edge_order (Optional[Sequence[Edge]], optional) – Manually specify the axis ordering of the final tensor.

Returns

The present object.

Return type

QuOperator

copy() β†’ tensorcircuit.quantum.QuOperator#

The deep copy of the operator.

Returns

The new copy of the operator.

Return type

QuOperator

eval(final_edge_order: Optional[Sequence[tensornetwork.network_components.Edge]] = None) β†’ Any#

Contracts the tensor network in place and returns the final tensor. Note that this modifies the tensor network representing the operator. The default ordering for the axes of the final tensor is: *out_edges, *in_edges. If there are any β€œignored” edges, their axes come first: *ignored_edges, *out_edges, *in_edges.

Parameters

final_edge_order (Optional[Sequence[Edge]], optional) – Manually specify the axis ordering of the final tensor. The default ordering is determined by out_edges and in_edges (see above).

Raises

ValueError – Node count β€˜{}’ > 1 after contraction!

Returns

The final tensor representing the operator.

Return type

Tensor

eval_matrix(final_edge_order: Optional[Sequence[tensornetwork.network_components.Edge]] = None) β†’ Any#

Contracts the tensor network in place and returns the final tensor in two dimentional matrix. The default ordering for the axes of the final tensor is: (\(\prod\) dimension of out_edges, \(\prod\) dimension of in_edges)

Parameters

final_edge_order (Optional[Sequence[Edge]], optional) – Manually specify the axis ordering of the final tensor. The default ordering is determined by out_edges and in_edges (see above).

Raises

ValueError – Node count β€˜{}’ > 1 after contraction!

Returns

The two-dimentional tensor representing the operator.

Return type

Tensor

classmethod from_local_tensor(tensor: Any, space: Sequence[int], loc: Sequence[int], out_axes: Optional[Sequence[int]] = None, in_axes: Optional[Sequence[int]] = None) β†’ tensorcircuit.quantum.QuOperator#
classmethod from_tensor(tensor: Any, subsystem_axes: Optional[Sequence[int]] = None) β†’ tensorcircuit.quantum.QuAdjointVector[source]#

Construct a QuAdjointVector directly from a single tensor. This first wraps the tensor in a Node, then constructs the QuAdjointVector from that Node.

Example

def show_attributes(op):
    print(f"op.is_scalar() \t\t-> {op.is_scalar()}")
    print(f"op.is_vector() \t\t-> {op.is_vector()}")
    print(f"op.is_adjoint_vector() \t-> {op.is_adjoint_vector()}")
    print(f"op.eval() \n{op.eval()}")
>>> psi_tensor = np.random.rand(2, 2)
>>> psi_tensor
array([[0.27260127, 0.91401091],
       [0.06490953, 0.38653646]])
>>> op = qu.QuAdjointVector.from_tensor(psi_tensor, [0, 1])
>>> show_attributes(op)
op.is_scalar()          -> False
op.is_vector()          -> False
op.is_adjoint_vector()  -> True
op.eval()
[[0.27260127 0.91401091]
 [0.06490953 0.38653646]]
Parameters
  • tensor (Tensor) – The tensor for constructing an QuAdjointVector.

  • subsystem_axes (Optional[Sequence[int]], optional) – Sequence of integer indices specifying the order in which to interpret the axes as subsystems (input edges). If not specified, the axes are taken in ascending order.

Returns

The new constructed QuAdjointVector give from the given tensor.

Return type

QuAdjointVector

property in_space: List[int]#
is_adjoint_vector() β†’ bool#

Returns a bool indicating if QuOperator is an adjoint vector. Examples can be found in the QuOperator.from_tensor.

is_scalar() β†’ bool#

Returns a bool indicating if QuOperator is a scalar. Examples can be found in the QuOperator.from_tensor.

is_vector() β†’ bool#

Returns a bool indicating if QuOperator is a vector. Examples can be found in the QuOperator.from_tensor.

property nodes: Set[tensornetwork.network_components.AbstractNode]#

All tensor-network nodes involved in the operator.

norm() β†’ tensorcircuit.quantum.QuOperator#

The norm of the operator. This is the 2-norm (also known as the Frobenius or Hilbert-Schmidt norm).

property out_space: List[int]#
partial_trace(subsystems_to_trace_out: Collection[int]) β†’ tensorcircuit.quantum.QuOperator#

The partial trace of the operator. Subsystems to trace out are supplied as indices, so that dangling edges are connected to each other as: out_edges[i] ^ in_edges[i] for i in subsystems_to_trace_out This does not modify the original network. The original ordering of the remaining subsystems is maintained.

Parameters

subsystems_to_trace_out (Collection[int]) – Indices of subsystems to trace out.

Returns

A new QuOperator or QuScalar representing the result.

Return type

QuOperator

projector() β†’ tensorcircuit.quantum.QuOperator[source]#

The projector of the operator. The operator, as a linear operator, on the adjoint of the operator.

Set \(A\) is the operator in matrix form, then the projector of operator is defined as: \(A^\dagger A\)

Returns

The projector of the operator.

Return type

QuOperator

reduced_density(subsystems_to_trace_out: Collection[int]) β†’ tensorcircuit.quantum.QuOperator[source]#

The reduced density of the operator.

Set \(A\) is the matrix of the operator, then the reduced density is defined as:

\[\mathrm{Tr}_{subsystems}(A^\dagger A)\]

Firstly, take the projector of the operator, then trace out the subsystems to trace out are supplied as indices, so that dangling edges are connected to each other as: out_edges[i] ^ in_edges[i] for i in subsystems_to_trace_out This does not modify the original network. The original ordering of the remaining subsystems is maintained.

Parameters

subsystems_to_trace_out (Collection[int]) – Indices of subsystems to trace out.

Returns

The QuOperator of the reduced density of the operator with given subsystems.

Return type

QuOperator

property space: List[int]#
property subsystem_edges: List[tensornetwork.network_components.Edge]#
tensor_product(other: tensorcircuit.quantum.QuOperator) β†’ tensorcircuit.quantum.QuOperator#

Tensor product with another operator. Given two operators A and B, produces a new operator AB representing \(A βŠ— B\). The out_edges (in_edges) of AB is simply the concatenation of the out_edges (in_edges) of A.copy() with that of B.copy(): new_out_edges = [*out_edges_A_copy, *out_edges_B_copy] new_in_edges = [*in_edges_A_copy, *in_edges_B_copy]

Example

>>> psi = qu.QuVector.from_tensor(np.random.rand(2, 2))
>>> psi_psi = psi.tensor_product(psi)
>>> len(psi_psi.subsystem_edges)
4
>>> float(psi_psi.norm().eval())
2.9887872748523585
>>> psi.norm().eval() ** 2
2.9887872748523585
Parameters

other (QuOperator) – The other operator (B).

Returns

The result (AB).

Return type

QuOperator

trace() β†’ tensorcircuit.quantum.QuOperator#

The trace of the operator.

class tensorcircuit.quantum.QuOperator(out_edges: Sequence[tensornetwork.network_components.Edge], in_edges: Sequence[tensornetwork.network_components.Edge], ref_nodes: Optional[Collection[tensornetwork.network_components.AbstractNode]] = None, ignore_edges: Optional[Collection[tensornetwork.network_components.Edge]] = None)[source]#

Bases: object

Represents a linear operator via a tensor network. To interpret a tensor network as a linear operator, some of the dangling edges must be designated as out_edges (output edges) and the rest as in_edges (input edges). Considered as a matrix, the out_edges represent the row index and the in_edges represent the column index. The (right) action of the operator on another then consists of connecting the in_edges of the first operator to the out_edges of the second. Can be used to do simple linear algebra with tensor networks.

__init__(out_edges: Sequence[tensornetwork.network_components.Edge], in_edges: Sequence[tensornetwork.network_components.Edge], ref_nodes: Optional[Collection[tensornetwork.network_components.AbstractNode]] = None, ignore_edges: Optional[Collection[tensornetwork.network_components.Edge]] = None) β†’ None[source]#

Creates a new QuOperator from a tensor network. This encapsulates an existing tensor network, interpreting it as a linear operator. The network is checked for consistency: All dangling edges must either be in out_edges, in_edges, or ignore_edges.

Parameters
  • out_edges (Sequence[Edge]) – The edges of the network to be used as the output edges.

  • in_edges (Sequence[Edge]) – The edges of the network to be used as the input edges.

  • ref_nodes (Optional[Collection[AbstractNode]], optional) – Nodes used to refer to parts of the tensor network that are not connected to any input or output edges (for example: a scalar factor).

  • ignore_edges (Optional[Collection[Edge]], optional) – Optional collection of dangling edges to ignore when performing consistency checks.

Raises

ValueError – At least one reference node is required to specify a scalar. None provided!

adjoint() β†’ tensorcircuit.quantum.QuOperator[source]#

The adjoint of the operator. This creates a new QuOperator with complex-conjugate copies of all tensors in the network and with the input and output edges switched.

Returns

The adjoint of the operator.

Return type

QuOperator

check_network() β†’ None[source]#

Check that the network has the expected dimensionality. This checks that all input and output edges are dangling and that there are no other dangling edges (except any specified in ignore_edges). If not, an exception is raised.

contract(final_edge_order: Optional[Sequence[tensornetwork.network_components.Edge]] = None) β†’ tensorcircuit.quantum.QuOperator[source]#

Contract the tensor network in place. This modifies the tensor network representation of the operator (or vector, or scalar), reducing it to a single tensor, without changing the value.

Parameters

final_edge_order (Optional[Sequence[Edge]], optional) – Manually specify the axis ordering of the final tensor.

Returns

The present object.

Return type

QuOperator

copy() β†’ tensorcircuit.quantum.QuOperator[source]#

The deep copy of the operator.

Returns

The new copy of the operator.

Return type

QuOperator

eval(final_edge_order: Optional[Sequence[tensornetwork.network_components.Edge]] = None) β†’ Any[source]#

Contracts the tensor network in place and returns the final tensor. Note that this modifies the tensor network representing the operator. The default ordering for the axes of the final tensor is: *out_edges, *in_edges. If there are any β€œignored” edges, their axes come first: *ignored_edges, *out_edges, *in_edges.

Parameters

final_edge_order (Optional[Sequence[Edge]], optional) – Manually specify the axis ordering of the final tensor. The default ordering is determined by out_edges and in_edges (see above).

Raises

ValueError – Node count β€˜{}’ > 1 after contraction!

Returns

The final tensor representing the operator.

Return type

Tensor

eval_matrix(final_edge_order: Optional[Sequence[tensornetwork.network_components.Edge]] = None) β†’ Any[source]#

Contracts the tensor network in place and returns the final tensor in two dimentional matrix. The default ordering for the axes of the final tensor is: (\(\prod\) dimension of out_edges, \(\prod\) dimension of in_edges)

Parameters

final_edge_order (Optional[Sequence[Edge]], optional) – Manually specify the axis ordering of the final tensor. The default ordering is determined by out_edges and in_edges (see above).

Raises

ValueError – Node count β€˜{}’ > 1 after contraction!

Returns

The two-dimentional tensor representing the operator.

Return type

Tensor

classmethod from_local_tensor(tensor: Any, space: Sequence[int], loc: Sequence[int], out_axes: Optional[Sequence[int]] = None, in_axes: Optional[Sequence[int]] = None) β†’ tensorcircuit.quantum.QuOperator[source]#
classmethod from_tensor(tensor: Any, out_axes: Optional[Sequence[int]] = None, in_axes: Optional[Sequence[int]] = None) β†’ tensorcircuit.quantum.QuOperator[source]#

Construct a QuOperator directly from a single tensor. This first wraps the tensor in a Node, then constructs the QuOperator from that Node.

Example

def show_attributes(op):
    print(f"op.is_scalar() \t\t-> {op.is_scalar()}")
    print(f"op.is_vector() \t\t-> {op.is_vector()}")
    print(f"op.is_adjoint_vector() \t-> {op.is_adjoint_vector()}")
    print(f"op.eval() \n{op.eval()}")
>>> psi_tensor = np.random.rand(2, 2)
>>> psi_tensor
array([[0.27260127, 0.91401091],
       [0.06490953, 0.38653646]])
>>> op = qu.QuOperator.from_tensor(psi_tensor, out_axes=[0], in_axes=[1])
>>> show_attributes(op)
op.is_scalar()          -> False
op.is_vector()          -> False
op.is_adjoint_vector()  -> False
op.eval()
[[0.27260127 0.91401091]
 [0.06490953 0.38653646]]
Parameters
  • tensor (Tensor) – The tensor.

  • out_axes (Optional[Sequence[int]], optional) – The axis indices of tensor to use as out_edges.

  • in_axes (Optional[Sequence[int]], optional) – The axis indices of tensor to use as in_edges.

Returns

The new operator.

Return type

QuOperator

property in_space: List[int]#
is_adjoint_vector() β†’ bool[source]#

Returns a bool indicating if QuOperator is an adjoint vector. Examples can be found in the QuOperator.from_tensor.

is_scalar() β†’ bool[source]#

Returns a bool indicating if QuOperator is a scalar. Examples can be found in the QuOperator.from_tensor.

is_vector() β†’ bool[source]#

Returns a bool indicating if QuOperator is a vector. Examples can be found in the QuOperator.from_tensor.

property nodes: Set[tensornetwork.network_components.AbstractNode]#

All tensor-network nodes involved in the operator.

norm() β†’ tensorcircuit.quantum.QuOperator[source]#

The norm of the operator. This is the 2-norm (also known as the Frobenius or Hilbert-Schmidt norm).

property out_space: List[int]#
partial_trace(subsystems_to_trace_out: Collection[int]) β†’ tensorcircuit.quantum.QuOperator[source]#

The partial trace of the operator. Subsystems to trace out are supplied as indices, so that dangling edges are connected to each other as: out_edges[i] ^ in_edges[i] for i in subsystems_to_trace_out This does not modify the original network. The original ordering of the remaining subsystems is maintained.

Parameters

subsystems_to_trace_out (Collection[int]) – Indices of subsystems to trace out.

Returns

A new QuOperator or QuScalar representing the result.

Return type

QuOperator

tensor_product(other: tensorcircuit.quantum.QuOperator) β†’ tensorcircuit.quantum.QuOperator[source]#

Tensor product with another operator. Given two operators A and B, produces a new operator AB representing \(A βŠ— B\). The out_edges (in_edges) of AB is simply the concatenation of the out_edges (in_edges) of A.copy() with that of B.copy(): new_out_edges = [*out_edges_A_copy, *out_edges_B_copy] new_in_edges = [*in_edges_A_copy, *in_edges_B_copy]

Example

>>> psi = qu.QuVector.from_tensor(np.random.rand(2, 2))
>>> psi_psi = psi.tensor_product(psi)
>>> len(psi_psi.subsystem_edges)
4
>>> float(psi_psi.norm().eval())
2.9887872748523585
>>> psi.norm().eval() ** 2
2.9887872748523585
Parameters

other (QuOperator) – The other operator (B).

Returns

The result (AB).

Return type

QuOperator

trace() β†’ tensorcircuit.quantum.QuOperator[source]#

The trace of the operator.

class tensorcircuit.quantum.QuScalar(ref_nodes: Collection[tensornetwork.network_components.AbstractNode], ignore_edges: Optional[Collection[tensornetwork.network_components.Edge]] = None)[source]#

Bases: tensorcircuit.quantum.QuOperator

Represents a scalar via a tensor network.

__init__(ref_nodes: Collection[tensornetwork.network_components.AbstractNode], ignore_edges: Optional[Collection[tensornetwork.network_components.Edge]] = None) β†’ None[source]#

Constructs a new QuScalar from a tensor network. This encapsulates an existing tensor network, interpreting it as a scalar.

Parameters
  • ref_nodes (Collection[AbstractNode]) – Nodes used to refer to the tensor network (need not be exhaustive - one node from each disconnected subnetwork is sufficient).

  • ignore_edges (Optional[Collection[Edge]], optional) – Optional collection of edges to ignore when performing consistency checks.

adjoint() β†’ tensorcircuit.quantum.QuOperator#

The adjoint of the operator. This creates a new QuOperator with complex-conjugate copies of all tensors in the network and with the input and output edges switched.

Returns

The adjoint of the operator.

Return type

QuOperator

check_network() β†’ None#

Check that the network has the expected dimensionality. This checks that all input and output edges are dangling and that there are no other dangling edges (except any specified in ignore_edges). If not, an exception is raised.

contract(final_edge_order: Optional[Sequence[tensornetwork.network_components.Edge]] = None) β†’ tensorcircuit.quantum.QuOperator#

Contract the tensor network in place. This modifies the tensor network representation of the operator (or vector, or scalar), reducing it to a single tensor, without changing the value.

Parameters

final_edge_order (Optional[Sequence[Edge]], optional) – Manually specify the axis ordering of the final tensor.

Returns

The present object.

Return type

QuOperator

copy() β†’ tensorcircuit.quantum.QuOperator#

The deep copy of the operator.

Returns

The new copy of the operator.

Return type

QuOperator

eval(final_edge_order: Optional[Sequence[tensornetwork.network_components.Edge]] = None) β†’ Any#

Contracts the tensor network in place and returns the final tensor. Note that this modifies the tensor network representing the operator. The default ordering for the axes of the final tensor is: *out_edges, *in_edges. If there are any β€œignored” edges, their axes come first: *ignored_edges, *out_edges, *in_edges.

Parameters

final_edge_order (Optional[Sequence[Edge]], optional) – Manually specify the axis ordering of the final tensor. The default ordering is determined by out_edges and in_edges (see above).

Raises

ValueError – Node count β€˜{}’ > 1 after contraction!

Returns

The final tensor representing the operator.

Return type

Tensor

eval_matrix(final_edge_order: Optional[Sequence[tensornetwork.network_components.Edge]] = None) β†’ Any#

Contracts the tensor network in place and returns the final tensor in two dimentional matrix. The default ordering for the axes of the final tensor is: (\(\prod\) dimension of out_edges, \(\prod\) dimension of in_edges)

Parameters

final_edge_order (Optional[Sequence[Edge]], optional) – Manually specify the axis ordering of the final tensor. The default ordering is determined by out_edges and in_edges (see above).

Raises

ValueError – Node count β€˜{}’ > 1 after contraction!

Returns

The two-dimentional tensor representing the operator.

Return type

Tensor

classmethod from_local_tensor(tensor: Any, space: Sequence[int], loc: Sequence[int], out_axes: Optional[Sequence[int]] = None, in_axes: Optional[Sequence[int]] = None) β†’ tensorcircuit.quantum.QuOperator#
classmethod from_tensor(tensor: Any) β†’ tensorcircuit.quantum.QuScalar[source]#

Construct a QuScalar directly from a single tensor. This first wraps the tensor in a Node, then constructs the QuScalar from that Node.

Example

def show_attributes(op):
    print(f"op.is_scalar() \t\t-> {op.is_scalar()}")
    print(f"op.is_vector() \t\t-> {op.is_vector()}")
    print(f"op.is_adjoint_vector() \t-> {op.is_adjoint_vector()}")
    print(f"op.eval() \n{op.eval()}")
>>> op = qu.QuScalar.from_tensor(1.0)
>>> show_attributes(op)
op.is_scalar()          -> True
op.is_vector()          -> False
op.is_adjoint_vector()  -> False
op.eval()
1.0
Parameters

tensor (Tensor) – The tensor for constructing a new QuScalar.

Returns

The new constructed QuScalar from the given tensor.

Return type

QuScalar

property in_space: List[int]#
is_adjoint_vector() β†’ bool#

Returns a bool indicating if QuOperator is an adjoint vector. Examples can be found in the QuOperator.from_tensor.

is_scalar() β†’ bool#

Returns a bool indicating if QuOperator is a scalar. Examples can be found in the QuOperator.from_tensor.

is_vector() β†’ bool#

Returns a bool indicating if QuOperator is a vector. Examples can be found in the QuOperator.from_tensor.

property nodes: Set[tensornetwork.network_components.AbstractNode]#

All tensor-network nodes involved in the operator.

norm() β†’ tensorcircuit.quantum.QuOperator#

The norm of the operator. This is the 2-norm (also known as the Frobenius or Hilbert-Schmidt norm).

property out_space: List[int]#
partial_trace(subsystems_to_trace_out: Collection[int]) β†’ tensorcircuit.quantum.QuOperator#

The partial trace of the operator. Subsystems to trace out are supplied as indices, so that dangling edges are connected to each other as: out_edges[i] ^ in_edges[i] for i in subsystems_to_trace_out This does not modify the original network. The original ordering of the remaining subsystems is maintained.

Parameters

subsystems_to_trace_out (Collection[int]) – Indices of subsystems to trace out.

Returns

A new QuOperator or QuScalar representing the result.

Return type

QuOperator

tensor_product(other: tensorcircuit.quantum.QuOperator) β†’ tensorcircuit.quantum.QuOperator#

Tensor product with another operator. Given two operators A and B, produces a new operator AB representing \(A βŠ— B\). The out_edges (in_edges) of AB is simply the concatenation of the out_edges (in_edges) of A.copy() with that of B.copy(): new_out_edges = [*out_edges_A_copy, *out_edges_B_copy] new_in_edges = [*in_edges_A_copy, *in_edges_B_copy]

Example

>>> psi = qu.QuVector.from_tensor(np.random.rand(2, 2))
>>> psi_psi = psi.tensor_product(psi)
>>> len(psi_psi.subsystem_edges)
4
>>> float(psi_psi.norm().eval())
2.9887872748523585
>>> psi.norm().eval() ** 2
2.9887872748523585
Parameters

other (QuOperator) – The other operator (B).

Returns

The result (AB).

Return type

QuOperator

trace() β†’ tensorcircuit.quantum.QuOperator#

The trace of the operator.

class tensorcircuit.quantum.QuVector(subsystem_edges: Sequence[tensornetwork.network_components.Edge], ref_nodes: Optional[Collection[tensornetwork.network_components.AbstractNode]] = None, ignore_edges: Optional[Collection[tensornetwork.network_components.Edge]] = None)[source]#

Bases: tensorcircuit.quantum.QuOperator

Represents a (column) vector via a tensor network.

__init__(subsystem_edges: Sequence[tensornetwork.network_components.Edge], ref_nodes: Optional[Collection[tensornetwork.network_components.AbstractNode]] = None, ignore_edges: Optional[Collection[tensornetwork.network_components.Edge]] = None) β†’ None[source]#

Constructs a new QuVector from a tensor network. This encapsulates an existing tensor network, interpreting it as a (column) vector.

Parameters
  • subsystem_edges (Sequence[Edge]) – The edges of the network to be used as the output edges.

  • ref_nodes (Optional[Collection[AbstractNode]], optional) – Nodes used to refer to parts of the tensor network that are not connected to any input or output edges (for example: a scalar factor).

  • ignore_edges (Optional[Collection[Edge]], optional) – Optional collection of edges to ignore when performing consistency checks.

adjoint() β†’ tensorcircuit.quantum.QuOperator#

The adjoint of the operator. This creates a new QuOperator with complex-conjugate copies of all tensors in the network and with the input and output edges switched.

Returns

The adjoint of the operator.

Return type

QuOperator

check_network() β†’ None#

Check that the network has the expected dimensionality. This checks that all input and output edges are dangling and that there are no other dangling edges (except any specified in ignore_edges). If not, an exception is raised.

contract(final_edge_order: Optional[Sequence[tensornetwork.network_components.Edge]] = None) β†’ tensorcircuit.quantum.QuOperator#

Contract the tensor network in place. This modifies the tensor network representation of the operator (or vector, or scalar), reducing it to a single tensor, without changing the value.

Parameters

final_edge_order (Optional[Sequence[Edge]], optional) – Manually specify the axis ordering of the final tensor.

Returns

The present object.

Return type

QuOperator

copy() β†’ tensorcircuit.quantum.QuOperator#

The deep copy of the operator.

Returns

The new copy of the operator.

Return type

QuOperator

eval(final_edge_order: Optional[Sequence[tensornetwork.network_components.Edge]] = None) β†’ Any#

Contracts the tensor network in place and returns the final tensor. Note that this modifies the tensor network representing the operator. The default ordering for the axes of the final tensor is: *out_edges, *in_edges. If there are any β€œignored” edges, their axes come first: *ignored_edges, *out_edges, *in_edges.

Parameters

final_edge_order (Optional[Sequence[Edge]], optional) – Manually specify the axis ordering of the final tensor. The default ordering is determined by out_edges and in_edges (see above).

Raises

ValueError – Node count β€˜{}’ > 1 after contraction!

Returns

The final tensor representing the operator.

Return type

Tensor

eval_matrix(final_edge_order: Optional[Sequence[tensornetwork.network_components.Edge]] = None) β†’ Any#

Contracts the tensor network in place and returns the final tensor in two dimentional matrix. The default ordering for the axes of the final tensor is: (\(\prod\) dimension of out_edges, \(\prod\) dimension of in_edges)

Parameters

final_edge_order (Optional[Sequence[Edge]], optional) – Manually specify the axis ordering of the final tensor. The default ordering is determined by out_edges and in_edges (see above).

Raises

ValueError – Node count β€˜{}’ > 1 after contraction!

Returns

The two-dimentional tensor representing the operator.

Return type

Tensor

classmethod from_local_tensor(tensor: Any, space: Sequence[int], loc: Sequence[int], out_axes: Optional[Sequence[int]] = None, in_axes: Optional[Sequence[int]] = None) β†’ tensorcircuit.quantum.QuOperator#
classmethod from_tensor(tensor: Any, subsystem_axes: Optional[Sequence[int]] = None) β†’ tensorcircuit.quantum.QuVector[source]#

Construct a QuVector directly from a single tensor. This first wraps the tensor in a Node, then constructs the QuVector from that Node.

Example

def show_attributes(op):
    print(f"op.is_scalar() \t\t-> {op.is_scalar()}")
    print(f"op.is_vector() \t\t-> {op.is_vector()}")
    print(f"op.is_adjoint_vector() \t-> {op.is_adjoint_vector()}")
    print(f"op.eval() \n{op.eval()}")
>>> psi_tensor = np.random.rand(2, 2)
>>> psi_tensor
array([[0.27260127, 0.91401091],
       [0.06490953, 0.38653646]])
>>> op = qu.QuVector.from_tensor(psi_tensor, [0, 1])
>>> show_attributes(op)
op.is_scalar()          -> False
op.is_vector()          -> True
op.is_adjoint_vector()  -> False
op.eval()
[[0.27260127 0.91401091]
 [0.06490953 0.38653646]]
Parameters
  • tensor (Tensor) – The tensor for constructing a β€œQuVector”.

  • subsystem_axes (Optional[Sequence[int]], optional) – Sequence of integer indices specifying the order in which to interpret the axes as subsystems (output edges). If not specified, the axes are taken in ascending order.

Returns

The new constructed QuVector from the given tensor.

Return type

QuVector

property in_space: List[int]#
is_adjoint_vector() β†’ bool#

Returns a bool indicating if QuOperator is an adjoint vector. Examples can be found in the QuOperator.from_tensor.

is_scalar() β†’ bool#

Returns a bool indicating if QuOperator is a scalar. Examples can be found in the QuOperator.from_tensor.

is_vector() β†’ bool#

Returns a bool indicating if QuOperator is a vector. Examples can be found in the QuOperator.from_tensor.

property nodes: Set[tensornetwork.network_components.AbstractNode]#

All tensor-network nodes involved in the operator.

norm() β†’ tensorcircuit.quantum.QuOperator#

The norm of the operator. This is the 2-norm (also known as the Frobenius or Hilbert-Schmidt norm).

property out_space: List[int]#
partial_trace(subsystems_to_trace_out: Collection[int]) β†’ tensorcircuit.quantum.QuOperator#

The partial trace of the operator. Subsystems to trace out are supplied as indices, so that dangling edges are connected to each other as: out_edges[i] ^ in_edges[i] for i in subsystems_to_trace_out This does not modify the original network. The original ordering of the remaining subsystems is maintained.

Parameters

subsystems_to_trace_out (Collection[int]) – Indices of subsystems to trace out.

Returns

A new QuOperator or QuScalar representing the result.

Return type

QuOperator

projector() β†’ tensorcircuit.quantum.QuOperator[source]#

The projector of the operator. The operator, as a linear operator, on the adjoint of the operator.

Set \(A\) is the operator in matrix form, then the projector of operator is defined as: \(A A^\dagger\)

Returns

The projector of the operator.

Return type

QuOperator

reduced_density(subsystems_to_trace_out: Collection[int]) β†’ tensorcircuit.quantum.QuOperator[source]#

The reduced density of the operator.

Set \(A\) is the matrix of the operator, then the reduced density is defined as:

\[\mathrm{Tr}_{subsystems}(A A^\dagger)\]

Firstly, take the projector of the operator, then trace out the subsystems to trace out are supplied as indices, so that dangling edges are connected to each other as: out_edges[i] ^ in_edges[i] for i in subsystems_to_trace_out This does not modify the original network. The original ordering of the remaining subsystems is maintained.

Parameters

subsystems_to_trace_out (Collection[int]) – Indices of subsystems to trace out.

Returns

The QuOperator of the reduced density of the operator with given subsystems.

Return type

QuOperator

property space: List[int]#
property subsystem_edges: List[tensornetwork.network_components.Edge]#
tensor_product(other: tensorcircuit.quantum.QuOperator) β†’ tensorcircuit.quantum.QuOperator#

Tensor product with another operator. Given two operators A and B, produces a new operator AB representing \(A βŠ— B\). The out_edges (in_edges) of AB is simply the concatenation of the out_edges (in_edges) of A.copy() with that of B.copy(): new_out_edges = [*out_edges_A_copy, *out_edges_B_copy] new_in_edges = [*in_edges_A_copy, *in_edges_B_copy]

Example

>>> psi = qu.QuVector.from_tensor(np.random.rand(2, 2))
>>> psi_psi = psi.tensor_product(psi)
>>> len(psi_psi.subsystem_edges)
4
>>> float(psi_psi.norm().eval())
2.9887872748523585
>>> psi.norm().eval() ** 2
2.9887872748523585
Parameters

other (QuOperator) – The other operator (B).

Returns

The result (AB).

Return type

QuOperator

trace() β†’ tensorcircuit.quantum.QuOperator#

The trace of the operator.

tensorcircuit.quantum.check_spaces(edges_1: Sequence[tensornetwork.network_components.Edge], edges_2: Sequence[tensornetwork.network_components.Edge]) β†’ None[source]#

Check the vector spaces represented by two lists of edges are compatible. The number of edges must be the same and the dimensions of each pair of edges must match. Otherwise, an exception is raised.

Parameters
  • edges_1 (Sequence[Edge]) – List of edges representing a many-body Hilbert space.

  • edges_2 (Sequence[Edge]) – List of edges representing a many-body Hilbert space.

Raises

ValueError – Hilbert-space mismatch: β€œCannot connect {} subsystems with {} subsystems”, or β€œInput dimension {} != output dimension {}.”

tensorcircuit.quantum.correlation_from_counts(index: Sequence[int], results: Any) β†’ Any[source]#

Compute \(\prod_{i\in \\text{index}} s_i\), where the probability for each bitstring is given as a vector results. Results is in the format of β€œcount_vector”

Example

>>> prob = tc.array_to_tensor(np.array([0.6, 0.4, 0, 0]))
>>> qu.correlation_from_counts([0, 1], prob)
(0.20000002+0j)
>>> qu.correlation_from_counts([1], prob)
(0.20000002+0j)
Parameters
  • index (Sequence[int]) – list of int, indicating the position in the bitstring

  • results (Tensor) – probability vector of shape 2^n

Returns

Correlation expectation from measurement shots.

Return type

Tensor

tensorcircuit.quantum.correlation_from_samples(index: Sequence[int], results: Any, n: int) β†’ Any[source]#

Compute \(\prod_{i\in \\text{index}} s_i (s=\pm 1)\), Results is in the format of β€œsample_int” or β€œsample_bin”

Parameters
  • index (Sequence[int]) – list of int, indicating the position in the bitstring

  • results (Tensor) – sample tensor

  • n (int) – number of qubits

Returns

Correlation expectation from measurement shots

Return type

Tensor

tensorcircuit.quantum.count_d2s(drepr: Any, eps: float = 1e-07) β†’ Tuple[Any, Any][source]#

measurement shots results, dense representation to sparse tuple representation non-jittable due to the non fixed return shape count_tuple to count_vector

Example

>>> tc.quantum.counts_d2s(np.array([0.1, 0, -0.3, 0.2]))
(array([0, 2, 3]), array([ 0.1, -0.3,  0.2]))
Parameters
  • drepr (Tensor) – [description]

  • eps (float, optional) – cutoff to determine nonzero elements, defaults to 1e-7

Returns

[description]

Return type

Tuple[Tensor, Tensor]

tensorcircuit.quantum.count_s2d(srepr: Tuple[Any, Any], n: int) β†’ Any[source]#

measurement shots results, sparse tuple representation to dense representation count_vector to count_tuple

Parameters
  • srepr (Tuple[Tensor, Tensor]) – [description]

  • n (int) – number of qubits

Returns

[description]

Return type

Tensor

tensorcircuit.quantum.count_t2v(drepr: Any, eps: float = 1e-07) β†’ Tuple[Any, Any]#

measurement shots results, dense representation to sparse tuple representation non-jittable due to the non fixed return shape count_tuple to count_vector

Example

>>> tc.quantum.counts_d2s(np.array([0.1, 0, -0.3, 0.2]))
(array([0, 2, 3]), array([ 0.1, -0.3,  0.2]))
Parameters
  • drepr (Tensor) – [description]

  • eps (float, optional) – cutoff to determine nonzero elements, defaults to 1e-7

Returns

[description]

Return type

Tuple[Tensor, Tensor]

tensorcircuit.quantum.count_tuple2dict(count: Tuple[Any, Any], n: int, key: str = 'bin') β†’ Dict[Any, int][source]#

count_tuple to count_dict_bin or count_dict_int

Parameters
  • count (Tuple[Tensor, Tensor]) – count_tuple format

  • n (int) – number of qubits

  • key (str, optional) – can be β€œint” or β€œbin”, defaults to β€œbin”

Returns

count_dict

Return type

_type_

tensorcircuit.quantum.count_vector2dict(count: Any, n: int, key: str = 'bin') β†’ Dict[Any, int][source]#

convert_vector to count_dict_bin or count_dict_int

Parameters
  • count (Tensor) – tensor in shape [2**n]

  • n (int) – number of qubits

  • key (str, optional) – can be β€œint” or β€œbin”, defaults to β€œbin”

Returns

_description_

Return type

_type_

tensorcircuit.quantum.counts_v2t(srepr: Tuple[Any, Any], n: int) β†’ Any#

measurement shots results, sparse tuple representation to dense representation count_vector to count_tuple

Parameters
  • srepr (Tuple[Tensor, Tensor]) – [description]

  • n (int) – number of qubits

Returns

[description]

Return type

Tensor

tensorcircuit.quantum.double_state(h: Any, beta: float = 1) β†’ Any[source]#

Compute the double state of the given Hamiltonian operator h.

Parameters
  • h (Tensor) – Hamiltonian operator in form of Tensor.

  • beta (float, optional) – Constant for the optimization, default is 1.

Returns

The double state of h with the given beta.

Return type

Tensor

tensorcircuit.quantum.eliminate_identities(nodes: Collection[tensornetwork.network_components.AbstractNode]) β†’ Tuple[dict, dict][source]#

Eliminates any connected CopyNodes that are identity matrices. This will modify the network represented by nodes. Only identities that are connected to other nodes are eliminated.

Parameters

nodes (Collection[AbstractNode]) – Collection of nodes to search.

Returns

The Dictionary mapping remaining Nodes to any replacements, Dictionary specifying all dangling-edge replacements.

Return type

Dict[Union[CopyNode, AbstractNode], Union[Node, AbstractNode]], Dict[Edge, Edge]

tensorcircuit.quantum.entanglement_entropy(state: Any, cut: Union[int, List[int]]) β†’ Any[source]#
tensorcircuit.quantum.entanglement_negativity(rho: Any, transposed_sites: List[int]) β†’ Any[source]#

_summary_

Parameters
  • rho (Tensor) – _description_

  • transposed_sites (List[int]) – _description_

Returns

_description_

Return type

Tensor

tensorcircuit.quantum.entropy(rho: Union[Any, tensorcircuit.quantum.QuOperator], eps: Optional[float] = None) β†’ Any[source]#

Compute the entropy from the given density matrix rho.

Example

@partial(tc.backend.jit, jit_compile=False, static_argnums=(1, 2))
def entanglement1(param, n, nlayers):
    c = tc.Circuit(n)
    c = tc.templates.blocks.example_block(c, param, nlayers)
    w = c.wavefunction()
    rm = qu.reduced_density_matrix(w, int(n / 2))
    return qu.entropy(rm)

@partial(tc.backend.jit, jit_compile=False, static_argnums=(1, 2))
def entanglement2(param, n, nlayers):
    c = tc.Circuit(n)
    c = tc.templates.blocks.example_block(c, param, nlayers)
    w = c.get_quvector()
    rm = w.reduced_density([i for i in range(int(n / 2))])
    return qu.entropy(rm)
>>> param = tc.backend.ones([6, 6])
>>> tc.backend.trace(param)
>>> entanglement1(param, 6, 3)
1.3132654
>>> entanglement2(param, 6, 3)
1.3132653
Parameters
  • rho (Union[Tensor, QuOperator]) – The density matrix in form of Tensor or QuOperator.

  • eps (float) – Epsilon, default is 1e-12.

Returns

Entropy on the given density matrix.

Return type

Tensor

tensorcircuit.quantum.fidelity(rho: Any, rho0: Any) β†’ Any[source]#

Return fidelity scalar between two states rho and rho0.

\[\operatorname{Tr}(\sqrt{\sqrt{rho} rho_0 \sqrt{rho}})\]
Parameters
  • rho (Tensor) – The density matrix in form of Tensor.

  • rho0 (Tensor) – The density matrix in form of Tensor.

Returns

The sqrtm of a Hermitian matrix a.

Return type

Tensor

tensorcircuit.quantum.free_energy(rho: Union[Any, tensorcircuit.quantum.QuOperator], h: Union[Any, tensorcircuit.quantum.QuOperator], beta: float = 1, eps: float = 1e-12) β†’ Any[source]#

Compute the free energy of the given density matrix.

Example

>>> rho = np.array([[1.0, 0], [0, 0]])
>>> h = np.array([[-1.0, 0], [0, 1]])
>>> qu.free_energy(rho, h, 0.5)
-0.9999999999979998
>>> hq = qu.QuOperator.from_tensor(h)
>>> qu.free_energy(rho, hq, 0.5)
array([[-1.]])
Parameters
  • rho (Union[Tensor, QuOperator]) – The density matrix in form of Tensor or QuOperator.

  • h (Union[Tensor, QuOperator]) – Hamiltonian operator in form of Tensor or QuOperator.

  • beta (float, optional) – Constant for the optimization, default is 1.

  • eps (float, optional) – Epsilon, default is 1e-12.

Returns

The free energy of the given density matrix with the Hamiltonian operator.

Return type

Tensor

tensorcircuit.quantum.generate_local_hamiltonian(*hlist: Sequence[Any], matrix_form: bool = True) β†’ Union[tensorcircuit.quantum.QuOperator, Any][source]#

Generate a local Hamiltonian operator based on the given sequence of Tensor. Note: further jit is recommended. For large Hilbert space, sparse Hamiltonian is recommended

Parameters
  • hlist (Sequence[Tensor]) – A sequence of Tensor.

  • matrix_form (bool, optional) – Return Hamiltonian operator in form of matrix, defaults to True.

Returns

The Hamiltonian operator in form of QuOperator or matrix.

Return type

Union[QuOperator, Tensor]

tensorcircuit.quantum.gibbs_state(h: Any, beta: float = 1) β†’ Any[source]#

Compute the Gibbs state of the given Hamiltonian operator h.

Parameters
  • h (Tensor) – Hamiltonian operator in form of Tensor.

  • beta (float, optional) – Constant for the optimization, default is 1.

Returns

The Gibbs state of h with the given beta.

Return type

Tensor

tensorcircuit.quantum.heisenberg_hamiltonian(g: Any, hzz: float = 1.0, hxx: float = 1.0, hyy: float = 1.0, hz: float = 0.0, hx: float = 0.0, hy: float = 0.0, sparse: bool = True, numpy: bool = False) β†’ Any[source]#

Generate Heisenberg Hamiltonian with possible external fields. Currently requires tensorflow installed

Example

>>> g = tc.templates.graphs.Line1D(6)
>>> h = qu.heisenberg_hamiltonian(g, sparse=False)
>>> tc.backend.eigh(h)[0][:10]
array([-11.2111025,  -8.4721365,  -8.472136 ,  -8.472136 ,  -6.       ,
        -5.123106 ,  -5.123106 ,  -5.1231055,  -5.1231055,  -5.1231055],
    dtype=float32)
Parameters
  • g (Graph) – input circuit graph

  • hzz (float) – zz coupling, default is 1.0

  • hxx (float) – xx coupling, default is 1.0

  • hyy (float) – yy coupling, default is 1.0

  • hz (float) – External field on z direction, default is 0.0

  • hx (float) – External field on y direction, default is 0.0

  • hy (float) – External field on x direction, default is 0.0

  • sparse (bool, defalts True) – Whether to return sparse Hamiltonian operator, default is True.

  • numpy (bool, defaults False,) – whether return the matrix in numpy or tensorflow form

Returns

Hamiltonian measurements

Return type

Tensor

tensorcircuit.quantum.identity(space: Sequence[int], dtype: Optional[Any] = None) β†’ tensorcircuit.quantum.QuOperator[source]#

Construct a β€˜QuOperator’ representing the identity on a given space. Internally, this is done by constructing β€˜CopyNode’s for each edge, with dimension according to β€˜space’.

Example

>>> E = qu.identity((2, 3, 4))
>>> float(E.trace().eval())
24.0
>>> tensor = np.random.rand(2, 2)
>>> psi = qu.QuVector.from_tensor(tensor)
>>> E = qu.identity((2, 2))
>>> psi.eval()
array([[0.03964233, 0.99298281],
       [0.38564989, 0.00950596]])
>>> (E @ psi).eval()
array([[0.03964233, 0.99298281],
       [0.38564989, 0.00950596]])
>>>
>>> (psi.adjoint() @ E @ psi).eval()
array(1.13640257)
>>> psi.norm().eval()
array(1.13640257)
Parameters
  • space (Sequence[int]) – A sequence of integers for the dimensions of the tensor product factors of the space (the edges in the tensor network).

  • dtype (Any type) – The data type by np.* (for conversion to dense). defaults None to tc dtype.

Returns

The desired identity operator.

Return type

QuOperator

tensorcircuit.quantum.log_negativity(rho: Any, transposed_sites: List[int], base: str = 'e') β†’ Any[source]#

_summary_

Parameters
  • rho (Tensor) – _description_

  • transposed_sites (List[int]) – _description_

  • base (str, optional) – whether use 2 based log or e based log, defaults to β€œe”

Returns

_description_

Return type

Tensor

tensorcircuit.quantum.measurement_counts(state: Any, counts: Optional[int] = 8192, format: str = 'count_vector', is_prob: bool = False, random_generator: Optional[Any] = None, status: Optional[Any] = None, jittable: bool = False) β†’ Any[source]#

Simulate the measuring of each qubit of p in the computational basis, thus producing output like that of qiskit.

Six formats of measurement counts results:

β€œsample_int”: # np.array([0, 0])

β€œsample_bin”: # [np.array([1, 0]), np.array([1, 0])]

β€œcount_vector”: # np.array([2, 0, 0, 0])

β€œcount_tuple”: # (np.array([0]), np.array([2]))

β€œcount_dict_bin”: # {β€œ00”: 2, β€œ01”: 0, β€œ10”: 0, β€œ11”: 0}

β€œcount_dict_int”: # {0: 2, 1: 0, 2: 0, 3: 0}

Example

>>> n = 4
>>> w = tc.backend.ones([2**n])
>>> tc.quantum.measurement_results(w, counts=3, format="sample_bin", jittable=True)
array([[0, 0, 1, 0],
    [0, 1, 1, 0],
    [0, 1, 1, 1]])
>>> tc.quantum.measurement_results(w, counts=3, format="sample_int", jittable=True)
array([ 7, 15, 11])
>>> tc.quantum.measurement_results(w, counts=3, format="count_vector", jittable=True)
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1])
>>> tc.quantum.measurement_results(w, counts=3, format="count_tuple")
(array([1, 2, 8]), array([1, 1, 1]))
>>> tc.quantum.measurement_results(w, counts=3, format="count_dict_bin")
{'0001': 1, '0011': 1, '1101': 1}
>>> tc.quantum.measurement_results(w, counts=3, format="count_dict_int")
{3: 1, 6: 2}
Parameters
  • state (Tensor) – The quantum state, assumed to be normalized, as either a ket or density operator.

  • counts (int) – The number of counts to perform.

  • shots (int) – alias for the argument counts

  • format (str) – defaults to be β€œdirect”, see supported format above

  • format – alias for the argument format

  • is_prob (bool) – if True, the state is directly regarded as a probability list, defaults to be False

  • random_generator (Optional[Any]) – random_generator, defaults to None

  • status (Optional[Tensor]) – external randomness given by tensor uniformly from [0, 1], if set, can overwrite random_generator

  • jittable (bool) – if True, jax backend try using a jittable count, defaults to False

Returns

The counts for each bit string measured.

Return type

Tuple[]

tensorcircuit.quantum.measurement_results(state: Any, counts: Optional[int] = 8192, format: str = 'count_vector', is_prob: bool = False, random_generator: Optional[Any] = None, status: Optional[Any] = None, jittable: bool = False) β†’ Any#

Simulate the measuring of each qubit of p in the computational basis, thus producing output like that of qiskit.

Six formats of measurement counts results:

β€œsample_int”: # np.array([0, 0])

β€œsample_bin”: # [np.array([1, 0]), np.array([1, 0])]

β€œcount_vector”: # np.array([2, 0, 0, 0])

β€œcount_tuple”: # (np.array([0]), np.array([2]))

β€œcount_dict_bin”: # {β€œ00”: 2, β€œ01”: 0, β€œ10”: 0, β€œ11”: 0}

β€œcount_dict_int”: # {0: 2, 1: 0, 2: 0, 3: 0}

Example

>>> n = 4
>>> w = tc.backend.ones([2**n])
>>> tc.quantum.measurement_results(w, counts=3, format="sample_bin", jittable=True)
array([[0, 0, 1, 0],
    [0, 1, 1, 0],
    [0, 1, 1, 1]])
>>> tc.quantum.measurement_results(w, counts=3, format="sample_int", jittable=True)
array([ 7, 15, 11])
>>> tc.quantum.measurement_results(w, counts=3, format="count_vector", jittable=True)
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1])
>>> tc.quantum.measurement_results(w, counts=3, format="count_tuple")
(array([1, 2, 8]), array([1, 1, 1]))
>>> tc.quantum.measurement_results(w, counts=3, format="count_dict_bin")
{'0001': 1, '0011': 1, '1101': 1}
>>> tc.quantum.measurement_results(w, counts=3, format="count_dict_int")
{3: 1, 6: 2}
Parameters
  • state (Tensor) – The quantum state, assumed to be normalized, as either a ket or density operator.

  • counts (int) – The number of counts to perform.

  • shots (int) – alias for the argument counts

  • format (str) – defaults to be β€œdirect”, see supported format above

  • format – alias for the argument format

  • is_prob (bool) – if True, the state is directly regarded as a probability list, defaults to be False

  • random_generator (Optional[Any]) – random_generator, defaults to None

  • status (Optional[Tensor]) – external randomness given by tensor uniformly from [0, 1], if set, can overwrite random_generator

  • jittable (bool) – if True, jax backend try using a jittable count, defaults to False

Returns

The counts for each bit string measured.

Return type

Tuple[]

tensorcircuit.quantum.mutual_information(s: Any, cut: Union[int, List[int]]) β†’ Any[source]#

Mutual information between AB subsystem described by cut.

Parameters
  • s (Tensor) – The density matrix in form of Tensor.

  • cut (Union[int, List[int]]) – The AB subsystem.

Returns

The mutual information between AB subsystem described by cut.

Return type

Tensor

tensorcircuit.quantum.op2tensor(fn: Callable[[...], Any], op_argnums: Union[int, Sequence[int]] = 0) β†’ Callable[[...], Any][source]#
tensorcircuit.quantum.partial_transpose(rho: Any, transposed_sites: List[int]) β†’ Any[source]#

_summary_

Parameters
  • rho (Tensor) – density matrix

  • transposed_sites (List[int]) – sites int list to be transposed

Returns

_description_

Return type

Tensor

tensorcircuit.quantum.ps2coo_core(idx_x: Any, idx_y: Any, idx_z: Any, weight: Any, nqubits: int) β†’ Tuple[Any, Any][source]#
tensorcircuit.quantum.ps2xyz(ps: List[int]) β†’ Dict[str, List[int]][source]#

pauli string list to xyz dict

# ps2xyz([1, 2, 2, 0]) = {β€œx”: [0], β€œy”: [1, 2], β€œz”: []}

Parameters

ps (List[int]) – _description_

Returns

_description_

Return type

Dict[str, List[int]]

tensorcircuit.quantum.quantum_constructor(out_edges: Sequence[tensornetwork.network_components.Edge], in_edges: Sequence[tensornetwork.network_components.Edge], ref_nodes: Optional[Collection[tensornetwork.network_components.AbstractNode]] = None, ignore_edges: Optional[Collection[tensornetwork.network_components.Edge]] = None) β†’ tensorcircuit.quantum.QuOperator[source]#

Constructs an appropriately specialized QuOperator. If there are no edges, creates a QuScalar. If the are only output (input) edges, creates a QuVector (QuAdjointVector). Otherwise creates a QuOperator.

Example

def show_attributes(op):
    print(f"op.is_scalar()              -> {op.is_scalar()}")
    print(f"op.is_vector()              -> {op.is_vector()}")
    print(f"op.is_adjoint_vector()      -> {op.is_adjoint_vector()}")
    print(f"len(op.out_edges)   -> {len(op.out_edges)}")
    print(f"len(op.in_edges)    -> {len(op.in_edges)}")
>>> psi_node = tn.Node(np.random.rand(2, 2))
>>>
>>> op = qu.quantum_constructor([psi_node[0]], [psi_node[1]])
>>> show_attributes(op)
op.is_scalar()          -> False
op.is_vector()          -> False
op.is_adjoint_vector()  -> False
len(op.out_edges)       -> 1
len(op.in_edges)        -> 1
>>> # psi_node[0] -> op.out_edges[0]
>>> # psi_node[1] -> op.in_edges[0]
>>> op = qu.quantum_constructor([psi_node[0], psi_node[1]], [])
>>> show_attributes(op)
op.is_scalar()          -> False
op.is_vector()          -> True
op.is_adjoint_vector()  -> False
len(op.out_edges)       -> 2
len(op.in_edges)        -> 0
>>> # psi_node[0] -> op.out_edges[0]
>>> # psi_node[1] -> op.out_edges[1]
>>> op = qu.quantum_constructor([], [psi_node[0], psi_node[1]])
>>> show_attributes(op)
op.is_scalar()          -> False
op.is_vector()          -> False
op.is_adjoint_vector()  -> True
len(op.out_edges)       -> 0
len(op.in_edges)        -> 2
>>> # psi_node[0] -> op.in_edges[0]
>>> # psi_node[1] -> op.in_edges[1]
Parameters
  • out_edges (Sequence[Edge]) – A list of output edges.

  • in_edges (Sequence[Edge]) – A list of input edges.

  • ref_nodes (Optional[Collection[AbstractNode]], optional) – Reference nodes for the tensor network (needed if there is a. scalar component).

  • ignore_edges (Optional[Collection[Edge]], optional) – Edges to ignore when checking the dimensionality of the tensor network.

Returns

The new created QuOperator object.

Return type

QuOperator

tensorcircuit.quantum.quimb2qop(qb_mpo: Any) β†’ tensorcircuit.quantum.QuOperator[source]#

Convert MPO in Quimb package to QuOperator.

Parameters

tn_mpo (quimb.tensor.tensor_gen.*) – MPO in the form of Quimb package

Returns

MPO in the form of QuOperator

Return type

QuOperator

tensorcircuit.quantum.reduced_density_matrix(state: Union[Any, tensorcircuit.quantum.QuOperator], cut: Union[int, List[int]], p: Optional[Any] = None) β†’ Union[Any, tensorcircuit.quantum.QuOperator][source]#

Compute the reduced density matrix from the quantum state state.

Parameters
  • state (Union[Tensor, QuOperator]) – The quantum state in form of Tensor or QuOperator.

  • cut (Union[int, List[int]]) – the index list that is traced out, if cut is a int, it indicates [0, cut] as the traced out region

  • p (Optional[Tensor]) – probability decoration, default is None.

Returns

The reduced density matrix.

Return type

Union[Tensor, QuOperator]

tensorcircuit.quantum.reduced_wavefunction(state: Any, cut: List[int], measure: Optional[List[int]] = None) β†’ Any[source]#

Compute the reduced wavefunction from the quantum state state. The fixed measure result is guaranteed by users, otherwise final normalization may required in the return

Parameters
  • state (Tensor) – _description_

  • cut (List[int]) – the list of position for qubit to be reduced

  • measure (List[int]) – the fixed results of given qubits in the same shape list as cut

Returns

_description_

Return type

Tensor

tensorcircuit.quantum.renyi_entropy(rho: Union[Any, tensorcircuit.quantum.QuOperator], k: int = 2) β†’ Any[source]#

Compute the RΓ©nyi entropy of order \(k\) by given density matrix.

Parameters
  • rho (Union[Tensor, QuOperator]) – The density matrix in form of Tensor or QuOperator.

  • k (int, optional) – The order of RΓ©nyi entropy, default is 2.

Returns

The \(k\) th order of RΓ©nyi entropy.

Return type

Tensor

tensorcircuit.quantum.renyi_free_energy(rho: Union[Any, tensorcircuit.quantum.QuOperator], h: Union[Any, tensorcircuit.quantum.QuOperator], beta: float = 1, k: int = 2) β†’ Any[source]#

Compute the RΓ©nyi free energy of the corresponding density matrix and Hamiltonian.

Example

>>> rho = np.array([[1.0, 0], [0, 0]])
>>> h = np.array([[-1.0, 0], [0, 1]])
>>> qu.renyi_free_energy(rho, h, 0.5)
-1.0
>>> qu.free_energy(rho, h, 0.5)
-0.9999999999979998
Parameters
  • rho (Union[Tensor, QuOperator]) – The density matrix in form of Tensor or QuOperator.

  • h (Union[Tensor, QuOperator]) – Hamiltonian operator in form of Tensor or QuOperator.

  • beta (float, optional) – Constant for the optimization, default is 1.

  • k (int, optional) – The order of RΓ©nyi entropy, default is 2.

Returns

The \(k\) th order of RΓ©nyi entropy.

Return type

Tensor

tensorcircuit.quantum.sample2all(sample: Any, n: int, format: str = 'count_vector', jittable: bool = False) β†’ Any[source]#

transform sample_int or sample_bin form results to other forms specified by format

Parameters
  • sample (Tensor) – measurement shots results in sample_int or sample_bin format

  • n (int) – number of qubits

  • format (str, optional) – see the doc in the doc in tensorcircuit.quantum.measurement_results(), defaults to β€œcount_vector”

  • format – alias for the argument format

  • jittable (bool, optional) – only applicable to count transformation in jax backend, defaults to False

Returns

measurement results specified as format

Return type

Any

tensorcircuit.quantum.sample2count(sample: Any, n: int, jittable: bool = True) β†’ Tuple[Any, Any][source]#

sample_int to count_tuple

Parameters
  • sample (Tensor) – _description_

  • n (int) – _description_

  • jittable (bool, optional) – _description_, defaults to True

Returns

_description_

Return type

Tuple[Tensor, Tensor]

tensorcircuit.quantum.sample_bin2int(sample: Any, n: int) β†’ Any[source]#

bin sample to int sample

Parameters
  • sample (Tensor) – in shape [trials, n] of elements (0, 1)

  • n (int) – number of qubits

Returns

in shape [trials]

Return type

Tensor

tensorcircuit.quantum.sample_int2bin(sample: Any, n: int) β†’ Any[source]#

int sample to bin sample

Parameters
  • sample (Tensor) – in shape [trials] of int elements in the range [0, 2**n)

  • n (int) – number of qubits

Returns

in shape [trials, n] of element (0, 1)

Return type

Tensor

tensorcircuit.quantum.spin_by_basis(n: int, m: int, elements: Tuple[int, int] = (1, - 1)) β†’ Any[source]#

Generate all n-bitstrings as an array, each row is a bitstring basis. Return m-th col.

Example

>>> qu.spin_by_basis(2, 1)
array([ 1, -1,  1, -1])
Parameters
  • n (int) – length of a bitstring

  • m (int) – m<n,

  • elements (Tuple[int, int], optional) – the binary elements to generate, default is (1, -1).

Returns

The value for the m-th position in bitstring when going through all bitstring basis.

Return type

Tensor

tensorcircuit.quantum.taylorlnm(x: Any, k: int) β†’ Any[source]#

Taylor expansion of \(ln(x+1)\).

Parameters
  • x (Tensor) – The density matrix in form of Tensor.

  • k (int, optional) – The \(k\) th order, default is 2.

Returns

The \(k\) th order of Taylor expansion of \(ln(x+1)\).

Return type

Tensor

tensorcircuit.quantum.tn2qop(tn_mpo: Any) β†’ tensorcircuit.quantum.QuOperator[source]#

Convert MPO in TensorNetwork package to QuOperator.

Parameters

tn_mpo (tn.matrixproductstates.mpo.*) – MPO in the form of TensorNetwork package

Returns

MPO in the form of QuOperator

Return type

QuOperator

tensorcircuit.quantum.trace_distance(rho: Any, rho0: Any, eps: float = 1e-12) β†’ Any[source]#

Compute the trace distance between two density matrix rho and rho2.

Parameters
  • rho (Tensor) – The density matrix in form of Tensor.

  • rho0 (Tensor) – The density matrix in form of Tensor.

  • eps (float, optional) – Epsilon, defaults to 1e-12

Returns

The trace distance between two density matrix rho and rho2.

Return type

Tensor

tensorcircuit.quantum.trace_product(*o: Union[Any, tensorcircuit.quantum.QuOperator]) β†’ Any[source]#

Compute the trace of several inputs o as tensor or QuOperator.

\[\operatorname{Tr}(\prod_i O_i)\]
Example

>>> o = np.ones([2, 2])
>>> h = np.eye(2)
>>> qu.trace_product(o, h)
2.0
>>> oq = qu.QuOperator.from_tensor(o)
>>> hq = qu.QuOperator.from_tensor(h)
>>> qu.trace_product(oq, hq)
array([[2.]])
>>> qu.trace_product(oq, h)
array([[2.]])
>>> qu.trace_product(o, hq)
array([[2.]])
Returns

The trace of several inputs.

Return type

Tensor

tensorcircuit.quantum.truncated_free_energy(rho: Any, h: Any, beta: float = 1, k: int = 2) β†’ Any[source]#

Compute the truncated free energy from the given density matrix rho.

Parameters
  • rho (Tensor) – The density matrix in form of Tensor.

  • h (Tensor) – Hamiltonian operator in form of Tensor.

  • beta (float, optional) – Constant for the optimization, default is 1.

  • k (int, optional) – The \(k\) th order, defaults to 2

Returns

The \(k\) th order of the truncated free energy.

Return type

Tensor

tensorcircuit.quantum.xyz2ps(xyz: Dict[str, List[int]], n: Optional[int] = None) β†’ List[int][source]#

xyz dict to pauli string list

Parameters
  • xyz (Dict[str, List[int]]) – _description_

  • n (Optional[int], optional) – _description_, defaults to None

Returns

_description_

Return type

List[int]