Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
out_order: List of edge labels specifying the output order.
backend: String specifying the backend to use. Defaults to
`tensornetwork.config.default_backend`.
Returns:
The result of the contraction. The result is returned as a `Node`
if all elements of `tensors` are `BaseNode` objects, else
it is returned as a `Tensor` object.
"""
if backend and (backend not in backend_factory._BACKENDS):
raise ValueError("Backend '{}' does not exist".format(backend))
if backend is None:
backend = config.default_backend
are_nodes = [isinstance(t, network_components.BaseNode) for t in tensors]
nodes = {t for t in tensors if isinstance(t, network_components.BaseNode)}
if not all([n.backend.name == backend for n in nodes]):
raise ValueError(
"Some nodes have backends different from '{}'".format(backend))
_tensors = []
for t in tensors:
if isinstance(t, network_components.BaseNode):
_tensors.append(t.tensor)
else:
_tensors.append(t)
nodes, con_edges, out_edges = ncon_network(
_tensors,
network_structure,
con_order=con_order,
out_order=out_order,
Returns:
`float` or `complex`: The dominant eigenvalue.
Node: The dominant eigenvector.
"""
D = self.bond_dimensions[0]
def mv(vector):
result = self.unit_cell_transfer_operator(
direction, self.backend.reshape(vector, (D, D)))
return self.backend.reshape(result.tensor, (D * D,))
if not initial_state:
initial_state = self.backend.randn((self.bond_dimensions[0]**2,),
dtype=self.dtype)
else:
if isinstance(initial_state, BaseNode):
initial_state = initial_state.tensor
initial_state = self.backend.reshape(initial_state,
(self.bond_dimensions[0]**2,))
#note: for real dtype eta and dens are real.
#but scipy.linalg.eigs returns complex dtypes in any case
#since we know that for an MPS transfer matrix the largest
#eigenvalue and corresponding eigenvector are real
# we cast them.
eta, dens = self.backend.eigs(
A=mv,
initial_state=initial_state,
num_krylov_vecs=num_krylov_vecs,
numeig=1,
tol=precision,
which='LR',
def reachable(inputs: Union[BaseNode, Iterable[BaseNode], Edge, Iterable[Edge]]
) -> Set[BaseNode]:
"""
Computes all nodes reachable from `node` or `edge.node1` by connected edges.
Args:
inputs: A `BaseNode`/`Edge` or collection of `BaseNodes`/`Edges`
Returns:
A set of `BaseNode` objects that can be reached from `node`
via connected edges.
Raises:
ValueError: If an unknown value for `strategy` is passed.
"""
if isinstance(inputs, BaseNode):
inputs = {inputs}
elif isinstance(inputs, Edge):
inputs = {inputs.node1}
elif isinstance(inputs, list) and all(isinstance(x, Edge) for x in inputs):
inputs = {x.node1 for x in inputs}
return _reachable(set(inputs))
node_group.create_dataset(
'edges',
dtype=string_type,
data=np.array([edge.name for edge in self.edges], dtype=object))
def fresh_edges(self, axis_names: Optional[List[Text]] = None) -> None:
if not axis_names:
axis_names = self.axis_names
if not axis_names:
axis_names = [str(i) for i in range(len(self.shape))]
for i in range(len(self.edges)):
new_edge = Edge(node1=self, axis1=i, name=axis_names[i])
self.add_edge(new_edge, i, True)
class Node(BaseNode):
"""
A Node represents a concrete tensor in a tensor network.
The number of edges for a node represents the rank of that tensor.
For example:
* A node with no edges means this node represents a scalar value.
* A node with a single edge means this node is a vector.
* A node with two edges represents a matrix.
* A node with three edges is a tensor of rank 3, etc.
Each node can have an arbitrary rank/number of edges, each of which can have
an arbitrary dimension.
"""
def __init__(self,
Args:
tensor: The concrete that is represented by this node, or a `BaseNode`
object. If a tensor is passed, it can be
be either a numpy array or the tensor-type of the used backend.
If a `BaseNode` is passed, the passed node has to have the same \
backend as given by `backend`.
name: Name of the node. Used primarily for debugging.
axis_names: List of names for each of the tensor's axes.
backend: The name of the backend or an instance of a `BaseBackend`.
Raises:
ValueError: If there is a repeated name in `axis_names` or if the length
doesn't match the shape of the tensor.
"""
if isinstance(tensor, BaseNode):
#always use the `Node`'s backend
backend = tensor.backend
tensor = tensor.tensor
if not backend:
backend = config.default_backend
if isinstance(backend, BaseBackend):
backend_obj = backend
else:
backend_obj = backend_factory.get_backend(backend)
self._tensor = backend_obj.convert_to_tensor(tensor)
super().__init__(
name=name,
axis_names=axis_names,
backend=backend_obj,
shape=backend_obj.shape_tuple(self._tensor))
tensor,
name=name,
axis_names=[ax for ax in axis_names],
backend=backend)
node.set_signature(signature)
return node
def __repr__(self) -> Text:
edges = self.get_all_edges()
return (f'{self.__class__.__name__}\n(\n'
f'name : {self.name!r},'
f'\ntensor : \n{self.tensor!r},'
f'\nedges : \n{edges!r} \n)')
class CopyNode(BaseNode):
def __init__(self,
rank: int,
dimension: int,
name: Optional[Text] = None,
axis_names: Optional[List[Text]] = None,
backend: Optional[Text] = None,
dtype: Type[np.number] = np.float64) -> None:
"""
Initialize a CopyNode:
Args:
rank: The rank of the tensor.
dimension: The dimension of each leg.
name: A name for the node.
axis_names: axis_names for the node.
backend: An optional backend for the node. If `None`, a default
con_order: List of edge labels specifying the contraction order.
out_order: List of edge labels specifying the output order.
backend: String specifying the backend to use. Defaults to
`tensornetwork.config.default_backend`.
Returns:
The result of the contraction. The result is returned as a `Node`
if all elements of `tensors` are `BaseNode` objects, else
it is returned as a `Tensor` object.
"""
if backend and (backend not in backend_factory._BACKENDS):
raise ValueError("Backend '{}' does not exist".format(backend))
if backend is None:
backend = config.default_backend
are_nodes = [isinstance(t, network_components.BaseNode) for t in tensors]
nodes = {t for t in tensors if isinstance(t, network_components.BaseNode)}
if not all([n.backend.name == backend for n in nodes]):
raise ValueError(
"Some nodes have backends different from '{}'".format(backend))
_tensors = []
for t in tensors:
if isinstance(t, network_components.BaseNode):
_tensors.append(t.tensor)
else:
_tensors.append(t)
nodes, con_edges, out_edges = ncon_network(
_tensors,
network_structure,
con_order=con_order,