def test_contract_path(backend, algorithm): np.random.seed(10) D, d, M = 100, 4, 10 mps = Node(np.random.rand(D, d, D), backend=backend) mpsc = Node(np.random.rand(D, d, D), backend=backend) L = Node(np.random.rand(M, D, D), backend=backend) mpo = Node(np.random.rand(M, M, d, d), backend=backend) L[0] ^ mpo[0] L[1] ^ mps[0] L[2] ^ mpsc[0] mps[1] ^ mpo[3] mpsc[1] ^ mpo[2] nodes = [mps, mpsc, mpo, L] path = path_contractors.path_solver(algorithm=algorithm, nodes=nodes) order = [mpo[1], mps[2], mpsc[2]] res = path_contractors.contract_path(path=path, nodes=nodes, output_edge_order=order) exp = ncon([mps.tensor, mpsc.tensor, L.tensor, mpo.tensor], [[1, 2, -2], [5, 4, -3], [3, 1, 5], [3, -1, 4, 2]], backend=backend) np.testing.assert_allclose(res.tensor, exp)
def test_sanity_check(): a = Node(np.eye(2), backend="tensorflow") b = Node(np.eye(2), backend="tensorflow") connect(a[0], b[0]) g = to_graphviz([a, b]) #pylint: disable=no-member assert isinstance(g, graphviz.Graph)
def f(x, n): x_slice = x[..., :n] n1 = Node(x_slice, backend="tensorflow") n2 = Node(x_slice, backend="tensorflow") connect(n1[0], n2[0]) connect(n1[1], n2[1]) connect(n1[2], n2[2]) return contract_between(n1, n2).get_tensor()
def test_node_small_matmul(backend): t1 = np.random.randn(2, 2) t2 = np.random.randn(2, 2) a = Node(t1, backend=backend) b = Node(t2, backend=backend) res = ncon_interface.ncon([a, b], [(1, -1), (1, -2)], backend=backend) np.testing.assert_allclose(res.tensor, t1.transpose() @ t2)
def f(x, n): x_slice = x[..., :n] n1 = Node(x_slice, backend="pytorch") n2 = Node(x_slice, backend="pytorch") connect(n1[0], n2[0]) connect(n1[1], n2[1]) connect(n1[2], n2[2]) return contract(flatten_edges_between(n1, n2)).get_tensor()
def test_return_type(backend): t1, t2 = np.ones((2, 2)), np.ones((2, 2)) n1, n2 = Node(t1, backend=backend), Node(t2, backend=backend) result_1 = ncon_interface.ncon([t1, t2], [(-1, 1), (1, -2)], backend=backend) result_2 = ncon_interface.ncon([n1, n2], [(-1, 1), (1, -2)], backend=backend) result_3 = ncon_interface.ncon([n1, t2], [(-1, 1), (1, -2)], backend=backend) assert isinstance(result_1, type(n1.backend.convert_to_tensor(t1))) assert isinstance(result_2, BaseNode) assert isinstance(result_3, type(n1.backend.convert_to_tensor(t1)))
def test_basic_network_without_backends_raises_error(): #pylint: disable=import-outside-toplevel #pylint: disable=reimported import tensornetwork with pytest.raises(ImportError): Node(np.ones((2, 2)), backend="jax") with pytest.raises(ImportError): Node(np.ones((2, 2)), backend="tensorflow") with pytest.raises(ImportError): Node(np.ones((2, 2)), backend="pytorch")
def eval_probability(node: tn.Node, normalize: bool = False) -> np.ndarray: if not isinstance(node, tn.Node): raise ValueError("Qubit must be of tensornetwork.Node type") elif len(node.get_all_nondangling()) != 0: raise ValueError("Tensor network must be contracted before taking \ probability amplitude") state = node.get_tensor() if normalize: state = np.abs(state) ** 2 state /= np.sum(state) return state.ravel()
def test_basic_graphmode(self): # pylint: disable=not-context-manager with tf.compat.v1.Graph().as_default(): a = Node(tf.ones(10), backend="tensorflow") b = Node(tf.ones(10), backend="tensorflow") e = connect(a[0], b[0]) final_tensor = contract(e).get_tensor() sess = tf.compat.v1.Session() final_val = sess.run(final_tensor) self.assertAllClose(final_val, 10.0)
def inner_network(): """Creates a (modified) `Inner1` contraction from `opt_einsum` tests.""" x = Node(np.ones([5, 2, 3, 4])) y = Node(np.ones([5, 3])) z = Node(np.ones([2, 4])) # pylint: disable=pointless-statement x[0] ^ y[0] x[1] ^ z[0] x[2] ^ y[1] x[3] ^ z[1] return [x, y, z]
def gemm_network(): """Creates 'GEMM1' contraction from `opt_einsum` tests.""" x = Node(np.ones([1, 2, 4])) y = Node(np.ones([1, 3])) z = Node(np.ones([2, 4, 3])) # pylint: disable=pointless-statement x[0] ^ y[0] x[1] ^ z[0] x[2] ^ z[1] y[1] ^ z[2] return [x, y, z]
def contractDiag(node: tn.Node, diag: np.array, edgeNum: int): node.tensor = np.transpose( node.tensor, [edgeNum] + [i for i in range(len(node.edges)) if i != edgeNum]) for i in range(node[0].dimension): node.tensor[i] *= diag[i] node.tensor = np.transpose( node.tensor, list(range(1, edgeNum + 1)) + [0] + list(range(edgeNum + 1, len(node.edges)))) return node
def test_node_outer_product(backend): t1 = np.array([1, 2, 3]) t2 = np.array([1, 2]) a = Node(t1, backend=backend) b = Node(t2, backend=backend) res = ncon_interface.ncon([a, b], [(-1, ), (-2, )], backend=backend) np.testing.assert_allclose(res.tensor, np.kron(t1, t2).reshape((3, 2))) res = ncon_interface.ncon([a, a, a, a], [(1, ), (1, ), (2, ), (2, )], backend=backend) np.testing.assert_allclose(res.tensor, 196)
def test_node_small_matmul_mixed_labels(backend): np.random.seed(10) t1 = np.random.randn(2, 2) t2 = np.random.randn(2, 2) a = Node(t1, backend=backend) b = Node(t2, backend=backend) res = ncon_interface.ncon([a, b], [('hi', -1), ('hi', '-ho')], backend=backend) np.testing.assert_allclose(res.tensor, t1.transpose() @ t2)
def test_node_outer_product_1_mixed_labels(backend): t1 = np.array([1, 2, 3]) t2 = np.array([1, 2]) a = Node(t1, backend=backend) b = Node(t2, backend=backend) res = ncon_interface.ncon([a, b], [('-hi', ), ('-ho', )], backend=backend) np.testing.assert_allclose(res.tensor, np.kron(t1, t2).reshape((3, 2))) res = ncon_interface.ncon([a, a, a, a], [('hi', ), ('hi', ), ('ho', ), ('ho', )], backend=backend) np.testing.assert_allclose(res.tensor, 196)
def test_disconnected_network(backend, path_algorithm): a = Node(np.array([2, 2]), backend=backend) b = Node(np.array([2, 2]), backend=backend) c = Node(np.array([2, 2]), backend=backend) d = Node(np.array([2, 2]), backend=backend) # pylint: disable=pointless-statement a[0] ^ b[0] c[0] ^ d[0] nodes = [a, b, c, d] with pytest.raises(ValueError): path_algorithm(nodes)
def test_node_outer_product_2(backend): np.random.seed(10) t1 = np.random.rand(10, 100) t2 = np.random.rand(8) a = Node(t1, backend=backend) b = Node(t2, backend=backend) res = ncon_interface.ncon([a, b], [(-1, -2), (-3, )], out_order=[-2, -1, -3], backend=backend) exp = np.einsum('ij,k->jik', t1, t2) np.testing.assert_allclose(res.tensor, exp)
def unifyLegs(node: tn.Node, leg1: int, leg2: int, cleanOriginal=True) -> tn.Node: shape = node.get_tensor().shape newTensor = np.reshape( node.get_tensor(), list(shape[:leg1]) + [shape[leg1] * shape[leg2]] + list(shape[leg2 + 1:])) if cleanOriginal: tn.remove_node(node) return tn.Node(newTensor)
def test_node_outer_product_2_mixed_labels(backend): np.random.seed(10) t1 = np.random.rand(10, 100) t2 = np.random.rand(8) a = Node(t1, backend=backend) b = Node(t2, backend=backend) res = ncon_interface.ncon([a, b], [(-1, '-hi'), ('-ho', )], out_order=['-hi', -1, '-ho'], backend=backend) exp = np.einsum('ij,k->jik', t1, t2) np.testing.assert_allclose(res.tensor, exp)
def test_gradient_decent(): a = Node(torch.autograd.Variable(torch.ones(10), requires_grad=True), backend="pytorch") b = Node(torch.ones(10), backend="pytorch") e = connect(a[0], b[0]) final_tensor = contract(e).get_tensor() opt = torch.optim.SGD([a.tensor], lr=0.001) opt.zero_grad() final_tensor.norm().backward() opt.step() np.testing.assert_allclose(final_tensor.data, 10) np.testing.assert_allclose(a.tensor.data, 0.999 * np.ones((10, ))) assert final_tensor == 10
def test_subgraph_contraction(backend, path_algorithm): a_tensor = np.arange(4).reshape((2, 2)) b_tensor = np.arange(4).reshape((2, 2)) + 10 c_tensor = np.arange(4).reshape((2, 2)) + 20 a = Node(a_tensor, backend=backend) b = Node(b_tensor, backend=backend) c = Node(c_tensor, backend=backend) a[0] ^ b[1] c[1] ^ b[0] remaining_edges = [c[0], a[1]] result = path_algorithm({a, b}, [b[0], a[1]]) np.testing.assert_allclose(result.tensor, b_tensor @ a_tensor) final = (c @ result).reorder_edges(remaining_edges) np.testing.assert_allclose(final.tensor, c_tensor @ b_tensor @ a_tensor)
def test_trace_edge(backend, path_algorithm): a = Node(np.ones((2, 2, 2, 2, 2)), backend=backend) b = Node(np.ones((2, 2, 2)), backend=backend) c = Node(np.ones((2, 2, 2)), backend=backend) # pylint: disable=pointless-statement a[0] ^ a[1] a[2] ^ b[0] a[3] ^ c[0] b[1] ^ c[1] b[2] ^ c[2] nodes = [a, b, c] node = path_algorithm(nodes) np.testing.assert_allclose(node.tensor, np.ones(2) * 32.0)
def test_ignore_edge_order_with_order(backend, path_algorithm): a = Node(np.ones((1, 1, 1)), backend=backend) b = Node(np.ones((1, 1, 1, 2, 3)), backend=backend) a[0] ^ b[0] a[1] ^ b[1] a[2] ^ b[2] e0 = b[3] e1 = b[4] final_node = path_algorithm({a, b}, [e1, e0], ignore_edge_order=True) assert set(final_node.edges) == {e0, e1}
def test_gradient_decent(self): # pylint: disable=not-context-manager with tf.compat.v1.Graph().as_default(): a = Node(tf.Variable(tf.ones(10)), backend="tensorflow") b = Node(tf.ones(10), backend="tensorflow") e = connect(a[0], b[0]) final_tensor = contract(e).get_tensor() opt = tf.compat.v1.train.GradientDescentOptimizer(0.001) train_op = opt.minimize(final_tensor) sess = tf.compat.v1.Session() sess.run(tf.compat.v1.global_variables_initializer()) self.assertAllClose(sess.run(final_tensor), 10.0) sess.run(train_op) self.assertLess(sess.run(final_tensor), 10.0)
def test_node_outer_product(backend): if backend == "jax": pytest.skip("Jax outer product support is currently broken.") t1 = np.array([1, 2, 3]) t2 = np.array([1, 2]) a = Node(t1, backend=backend) b = Node(t2, backend=backend) res = ncon_interface.ncon([a, b], [(-1, ), (-2, )], backend=backend) np.testing.assert_allclose(res.tensor, np.kron(t1, t2).reshape((3, 2))) res = ncon_interface.ncon([a, a, a, a], [(1, ), (1, ), (2, ), (2, )], backend=backend) np.testing.assert_allclose(res.tensor, 196)
def test_sanity_check(backend, path_algorithm): a = Node(np.eye(2), backend=backend) b = Node(np.ones((2, 7, 11)), backend=backend) c = Node(np.ones((7, 11, 13, 2)), backend=backend) d = Node(np.eye(13), backend=backend) # pylint: disable=pointless-statement a[0] ^ b[0] b[1] ^ c[0] b[2] ^ c[1] c[2] ^ d[1] c[3] ^ a[1] nodes = [a, b, c, d] final_node = path_algorithm(nodes) assert final_node.shape == (13, )
def test_passes_ignore_edge_order_from_auto(backend): a = Node(np.eye(2), backend=backend) b = Node(np.eye(2), backend=backend) c = Node(np.eye(2), backend=backend) d = Node(np.eye(2), backend=backend) e = Node(np.eye(2), backend=backend) # pylint: disable=pointless-statement a[1] ^ b[0] c[0] ^ d[1] c[1] ^ e[0] nodes = [a, b, c, d, e] try: auto(nodes, ignore_edge_order=True) except ValueError: pytest.fail("auto should pass ignore_edge_order when n >= 5 && n < 7")
def test_custom_sanity_check(backend): a = Node(np.ones(2), backend=backend) b = Node(np.ones((2, 5)), backend=backend) # pylint: disable=pointless-statement a[0] ^ b[0] nodes = [a, b] class PathOptimizer: def __call__(self, inputs, output, size_dict, memory_limit=None): return [(0, 1)] optimizer = PathOptimizer() final_node = path_contractors.custom(nodes, optimizer) np.testing.assert_allclose(final_node.tensor, np.ones(5) * 2.0)
def test_single_node(backend, path_algorithm): a = Node(np.ones((2, 2, 2)), backend=backend) # pylint: disable=pointless-statement a[0] ^ a[1] nodes = [a] node = path_algorithm(nodes) np.testing.assert_allclose(node.tensor, np.ones(2) * 2.0)
def test_node_invalid_order(backend): a = Node(np.ones((2, 2)), backend=backend) with pytest.raises(ValueError): ncon_interface.ncon([a, a], [(1, 2), (2, 1)], con_order=[2, 3], backend=backend) with pytest.raises(ValueError): ncon_interface.ncon([a, a], [(1, 2), (2, 1)], out_order=[-1], backend=backend) with pytest.raises(ValueError): ncon_interface.ncon([a, a], [('i1', 'i2'), ('i1', 'i2')], con_order=['i1'], out_order=[], backend=backend) with pytest.raises(ValueError): ncon_interface.ncon([a, a], [('i1', 'i2'), ('i1', 'i2')], con_order=['i1', 'i2'], out_order=['i1'], backend=backend) with pytest.raises(ValueError): ncon_interface.ncon([a, a], [('i1', 'i2'), ('i1', 'i2')], con_order=['i1', 'i1', 'i2'], out_order=[], backend=backend)