def test_outer_product(self): a = np.array([1, 2, 3]) b = np.array([1, 2]) res = ncon_interface.ncon([a, b], [(-1,), (-2,)]) self.assertAllClose(res, np.kron(a, b).reshape((3, 2))) res = ncon_interface.ncon([a, a, a, a], [(0,), (0,), (1,), (1,)]) self.assertEqual(res.numpy(), 196)
def test_order_spec(self): a = tf.ones((2, 2)) result = ncon_interface.ncon([a, a], [(-1, 0), (0, -2)], out_order=[-1, -2]) self.assertAllClose(result, tf.ones((2, 2)) * 2) result = ncon_interface.ncon([a, a], [(-1, 0), (0, -2)], con_order=[0]) self.assertAllClose(result, tf.ones((2, 2)) * 2) result = ncon_interface.ncon([a, a], [(-1, 0), (0, -2)], con_order=[0], out_order=[-1, -2]) self.assertAllClose(result, tf.ones((2, 2)) * 2)
def test_outer_product_2(backend): np.random.seed(10) a = np.random.rand(10, 100) b = np.random.rand(8) res = ncon_interface.ncon([a, b], [(-1, -2), (-3,)], out_order=[-2, -1, -3], backend=backend) exp = np.einsum('ij,k->jik', a, b) np.testing.assert_allclose(res, exp)
def test_invalid_order(self): a = tf.ones((2, 2)) with self.assertRaises(ValueError): ncon_interface.ncon([a, a], [(0, 1), (1, 0)], con_order=[1, 2]) with self.assertRaises(ValueError): ncon_interface.ncon([a, a], [(0, 1), (1, 0)], out_order=[-1]) with self.assertRaises(ValueError): ncon_interface.ncon([a, a], [('i1', 'i2'), ('i1', 'i2')], con_order=['i1'], out_order=[]) with self.assertRaises(ValueError): ncon_interface.ncon([a, a], [('i1', 'i2'), ('i1', 'i2')], con_order=['i1', 'i2'], out_order=['i1']) with self.assertRaises(ValueError): ncon_interface.ncon([a, a], [('i1', 'i2'), ('i1', 'i2')], con_order=['i1', 'i1', 'i2'], out_order=[])
def test_outer_product_2_mixed_labels(backend): np.random.seed(10) a = np.random.rand(10, 100) b = np.random.rand(8) res = ncon_interface.ncon([a, b], [(-1, '-hi'), ('-ho',)], out_order=['-hi', -1, '-ho'], backend=backend) exp = np.einsum('ij,k->jik', a, b) np.testing.assert_allclose(res, exp)
def test_node_small_matmul(backend): np.random.seed(10) t1 = np.random.randn(2, 2) t2 = np.random.randn(2, 2) a = Tensor(t1, backend=backend) b = Tensor(t2, backend=backend) res = ncon_interface.ncon([a, b], [(1, -1), (1, -2)], backend=backend) np.testing.assert_allclose(res.array, t1.transpose() @ t2)
def test_contraction_mixed_labels(backend): np.random.seed(10) a = np.random.randn(2, 2, 2) res = ncon_interface.ncon([a, a, a], [(-1, 'rick', 2), ('rick', 2, 'morty'), ('morty', -2, -3)], backend=backend) res_np = a.reshape((2, 4)) @ a.reshape((4, 2)) @ a.reshape((2, 4)) res_np = res_np.reshape((2, 2, 2)) np.testing.assert_allclose(res, res_np)
def test_partial_traces(backend): np.random.seed(10) a = np.random.rand(4, 4, 4, 4) res = ncon_interface.ncon([a, a], [(-1, 1, 1, 3), (2, -2, 2, 3)], backend=backend) t1 = np.trace(a, axis1=1, axis2=2) t2 = np.trace(a, axis1=0, axis2=2) exp = np.tensordot(t1, t2, ([1], [1])) np.testing.assert_allclose(res, exp)
def test_batched_matmul_3(backend): np.random.seed(10) batchsize = 10 a = np.random.randn(2, 4, 4, batchsize) b = np.random.randn(4, 3, batchsize, 5) c = np.random.randn(batchsize, 5, 4) res = ncon_interface.ncon([a, b, c], [(-1, 1, 2, 4), (1, -2, 4, 3), (4, 3, 2)], backend=backend) exp = np.einsum('abck,bdke,kec->ad', a, b, c) np.testing.assert_allclose(res, exp) res = ncon_interface.ncon([a, b, c], [(-1, 1, 2, 4), (1, -2, 4, 3), (4, 3, 2)], out_order=[-2, -1], backend=backend) exp = np.einsum('abck,bdke,kec->da', a, b, c) np.testing.assert_allclose(res, exp)
def test_node_contraction(backend): tensor = np.random.randn(2, 2, 2) a = Node(tensor, backend=backend) res = ncon_interface.ncon([a, a, a], [(-1, 1, 2), (1, 2, 3), (3, -2, -3)], backend=backend) res_np = tensor.reshape((2, 4)) @ tensor.reshape((4, 2)) @ tensor.reshape( (2, 4)) res_np = res_np.reshape((2, 2, 2)) np.testing.assert_allclose(res.tensor, res_np)
def compute_energy(self): self.mps.position(0) #move center position to the left end self.compute_right_envs() return ncon([ self.add_right_layer(self.right_envs[0], self.mps.tensors[0], self.mpo.tensors[0]), self.left_envs[0], ], [[1, 2, 3], [1, 2, 3]], backend=self.backend.name).item()
def test_invalid_order(): a = tf.ones((2, 2)) with pytest.raises(ValueError): ncon_interface.ncon([a, a], [(1, 2), (2, 1)], con_order=[2, 3]) with pytest.raises(ValueError): ncon_interface.ncon([a, a], [(1, 2), (2, 1)], out_order=[-1]) with pytest.raises(ValueError): ncon_interface.ncon([a, a], [('i1', 'i2'), ('i1', 'i2')], con_order=['i1'], out_order=[]) with pytest.raises(ValueError): ncon_interface.ncon([a, a], [('i1', 'i2'), ('i1', 'i2')], con_order=['i1', 'i2'], out_order=['i1']) with pytest.raises(ValueError): ncon_interface.ncon([a, a], [('i1', 'i2'), ('i1', 'i2')], con_order=['i1', 'i1', 'i2'], out_order=[])
def test_batched_matmul_1(backend): np.random.seed(10) a = np.random.randn(10, 11, 100) b = np.random.randn(11, 100, 12) res = ncon_interface.ncon([a, b], [(-1, 1, -3), (1, -3, -2)], backend=backend) exp = np.einsum('ijk,jkm->imk', a, b) np.testing.assert_allclose(res, exp) res = ncon_interface.ncon([a, b], [(-1, 1, -3), (1, -3, -2)], out_order=[-2, -1, -3], backend=backend) exp = np.einsum('ijk,jkm->mik', a, b) np.testing.assert_allclose(res, exp) res = ncon_interface.ncon([a, b], [(-1, 1, -3), (1, -3, -2)], out_order=[-3, -2, -1], backend=backend) exp = np.einsum('ijk,jkm->kmi', a, b) np.testing.assert_allclose(res, exp)
def doApplyMPO(psi,p,Larr,Marr,Rarr,c): """ function for applying MPO to state """ summ = 0 Q = len(Marr) for i in range(Q): summ += c[i]*ncon([psi.reshape(Larr[i][p].shape[2],Marr[i][p].shape[3],Marr[i][p+1].shape[3],Rarr[i][p+1].shape[2]),Larr[i][p],Marr[i][p],Marr[i][p+1],Rarr[i][p+1]], [[1,3,5,7],[2,-1,1],[2,4,-2,3],[4,6,-3,5],[6,-4,7]]).reshape( Larr[i][p].shape[2]*Marr[i][p].shape[3]*Marr[i][p+1].shape[3]*Rarr[i][p+1].shape[2]) return summ
def test_node_order_spec(backend): node = Node(np.ones((2, 2)), backend=backend) result = ncon_interface.ncon([node, node], [(-1, 1), (1, -2)], out_order=[-1, -2], backend=backend) np.testing.assert_allclose(result.tensor, np.ones((2, 2)) * 2) result = ncon_interface.ncon([node, node], [(-1, 1), (1, -2)], con_order=[1], backend=backend) np.testing.assert_allclose(result.tensor, np.ones((2, 2)) * 2) result = ncon_interface.ncon([node, node], [(-1, 1), (1, -2)], con_order=[1], out_order=[-1, -2], backend=backend) np.testing.assert_allclose(result.tensor, np.ones((2, 2)) * 2)
def test_order_spec(backend): a = np.ones((2, 2)) result = ncon_interface.ncon([a, a], [(-1, 1), (1, -2)], out_order=[-1, -2], backend=backend) np.testing.assert_allclose(result, np.ones((2, 2)) * 2) result = ncon_interface.ncon([a, a], [(-1, 1), (1, -2)], con_order=[1], backend=backend) np.testing.assert_allclose(result, np.ones((2, 2)) * 2) result = ncon_interface.ncon([a, a], [(-1, 1), (1, -2)], con_order=[1], out_order=[-1, -2], backend=backend) np.testing.assert_allclose(result, np.ones((2, 2)) * 2)
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_contraction_mixed_labels(backend): np.random.seed(10) tensor = np.random.randn(2, 2, 2) a = Tensor(tensor, backend=backend) res = ncon_interface.ncon([a, a, a], [(-1, 'rick', 2), ('rick', 2, 'morty'), ('morty', -2, -3)], backend=backend) res_np = tensor.reshape((2, 4)) @ tensor.reshape((4, 2)) @ tensor.reshape( (2, 4)) res_np = res_np.reshape((2, 2, 2)) np.testing.assert_allclose(res.array, res_np)
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_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 test_ncon_vs_backend(dtype, backend): shape = (4, 3) dtype = testing_utils.np_dtype_to_backend(backend, dtype) testing_utils.check_contraction_dtype(backend, dtype) tensor1 = tensornetwork.ones(shape, backend=backend, dtype=dtype) tensor2 = tensornetwork.ones(shape, backend=backend, dtype=dtype) tensor3 = tensornetwork.ones(shape, backend=backend, dtype=dtype) tensors = [tensor1, tensor2, tensor3] arrays = [tensor1.array, tensor2.array, tensor3.array] idxs = [[1, -1], [1, 2], [-2, 2]] result = ncon(tensors, idxs, backend=backend) old_result = tensornetwork.ncon(arrays, idxs, backend=backend) np.testing.assert_allclose(old_result, result.array)
def test_ncon_builder(backend): a, _ = testing_utils.safe_randn((2, 2, 2), backend, np.float32) b, _ = testing_utils.safe_randn((2, 2, 2), backend, np.float32) c, _ = testing_utils.safe_randn((2, 2, 2), backend, np.float32) tmp = a(2, 1, -1) assert tmp.tensors[0] is a assert tmp.axes[0] == [2, 1, -1] builder = a(2, 1, -1) @ b(2, 3, -2) @ c(1, 3, -3) assert builder.tensors == [a, b, c] assert builder.axes == [[2, 1, -1], [2, 3, -2], [1, 3, -3]] np.testing.assert_allclose( ncon_interface.ncon( [a, b, c], [[2, 1, -1], [2, 3, -2], [1, 3, -3]], backend=backend).array, ncon_interface.finalize(builder).array)
def apply_one_site_gate(self, gate: Tensor, site: int) -> None: """Apply a one-site gate to an MPS. This routine will in general destroy any canonical form of the state. If a canonical form is needed, the user can restore it using `FiniteMPS.position` Args: gate: a one-body gate site: the site where the gate should be applied """ if len(gate.shape) != 2: raise ValueError('rank of gate is {} but has to be 2'.format( len(gate.shape))) if site < 0 or site >= len(self): raise ValueError('site = {} is not between 0 <= site < N={}'.format( site, len(self))) self.tensors[site] = ncon([gate, self.tensors[site]], [[-2, 1], [-1, 1, -3]], backend=self.backend.name)
def createFactorTable_Su2CoarseGrain_2To1Site( W: 'list of pairs of Su2Tensors', wd: Su2Tensor, tableFileName: str) -> dict: """ (Precomputation.) Creates the factors and compatible chargesectors for the function Su2CoarseGrain_2To1Site() W: a list of pairs of SU(2) tensors wd: a SU(2) tensor (the isometry that blocks 2 lattice sites) tableFileName: file name to store the created factor table """ FactorTable = dict() # Dictionary from fusion trees to factors for k in range(len(W)): w1 = W[k][0] w2 = W[k][1] for c1 in w2.getAllBlocks(): for c2 in w1.getAllBlocks(): if c2[total] != c1[left]: continue for c3 in wd.getAllBlocks(): if c2[right] != c3[left] or c1[right] != c3[right] or not Su2Engine.compatible(c2[left], c3[total],\ c1[total]): continue for c4 in wd.getAllBlocks(): if c4[total] != c3[total]: continue for c5 in w1.getAllBlocks(): if c5[right] != c4[left] or c5[left] != c2[left] or not Su2Engine.compatible(c5[total],\ c4[right],c1[total]): continue for c6 in w2.getAllBlocks(): if c6[left] != c5[total] or c6[right] != c4[right] or c6[total] != c1[total]: continue C1 = Su2Engine.createCGtensor(c1[left], c1[right], c1[total]) C2 = Su2Engine.createCGtensor(c2[left], c2[right], c2[total]) C3 = Su2Engine.createCGtensor(c3[left], c3[right], c3[total]) C4 = Su2Engine.createCGtensor(c4[left], c4[right], c4[total]) C5 = Su2Engine.createCGtensor(c5[left], c5[right], c5[total]) C6 = Su2Engine.createCGtensor(c6[left], c6[right], c6[total]) Cmat = ncon([C1,C2,C3,C4,C5,C6],[[1,3,-1],[7,2,1],[2,3,8],[5,6,8],[7,5,4],[4,6,-2]]) FactorTable[FusionTree((c1[total],c1[left],c2[left],c2[right],c1[right],c3[total],\ c4[left],c4[right],c5[total]))] = Cmat[0][0] np.save(tableFileName, FactorTable) return FactorTable
def Su2CoarseGrain_1To1site( w: Su2Tensor, h: Su2Tensor) -> Su2Tensor: """ Coarse-grains (blocks) 1-site operator h through isometry w. w: the blocking isometry h: the 1-site SU(2)-symmetric operator """ hh = Su2Tensor(h.getIndices()) # the coarse-grained hamiltonian. Even though h is a 4-index tensor it is # stored as a 2-index matrix. So indices of h are the blocked 2-site indices wBlocks = w.getAllBlocks() # a dictionary {FusionTree:block} hBlocks = h.getAllBlocks() # a dictionary {FusionTree:block} for ft in wBlocks: ch = FusionTree((ft[1],ft[1])) if not ch in hBlocks: continue temp = ncon([wBlocks[ft],hBlocks[ch],wBlocks[ft]],[[-1, 1, 3],[1, 2],[-2, 2, 3]]) hh.addblock(FusionTree((ft[0],ft[0])),temp) return hh
def test_ncon_invalid_backends(dtype, backend): backend_names = set(["jax", "numpy", "tensorflow", "pytorch"]) this_name = set([backend]) other_backend_names = list(backend_names - this_name) shape = (4, 3) dtype1 = testing_utils.np_dtype_to_backend(backend, dtype) tensor1 = tensornetwork.ones(shape, backend=backend, dtype=dtype1) for other_backend in other_backend_names: dtype2 = testing_utils.np_dtype_to_backend(other_backend, dtype) tensor2 = tensornetwork.ones(shape, backend=other_backend, dtype=dtype2) for other_other_backend in backend_names: dtype3 = testing_utils.np_dtype_to_backend(other_other_backend, dtype) tensor3 = tensornetwork.zeros(shape, backend=other_other_backend, dtype=dtype3) tensors = [tensor1, tensor2, tensor3] idxs = [[1, -1], [1, 2], [-2, 2]] with pytest.raises(ValueError): _ = ncon(tensors, idxs)
def test_left_envs_all_sites(backend_dtype_values): backend = backend_factory.get_backend(backend_dtype_values[0]) dtype = backend_dtype_values[1] D, d, N = 3, 2, 5 tensors = [np.ones((1, d, D), dtype=dtype) ] + [np.ones((D, d, D), dtype=dtype) for _ in range(N - 2)] + [np.ones((D, d, 1), dtype=dtype)] mps = FiniteMPS(tensors, center_position=N // 2, backend=backend_dtype_values[0], canonicalize=True) l = backend.convert_to_tensor(np.ones((1, 1), dtype=dtype)) exp = {} for n, t in enumerate(mps.tensors): exp[n] = l l = ncon([t, l, t], [[1, 2, -1], [1, 3], [3, 2, -2]], backend=backend) envs = mps.left_envs(sites=range(N)) assert list(envs.keys()) == list(range(N)) for n in range(N): expected = exp[n] actual = envs[n] np.testing.assert_array_almost_equal(expected, actual)
def test_small_matmul(backend): a = np.random.randn(2, 2) b = np.random.randn(2, 2) res = ncon_interface.ncon([a, b], [(1, -1), (1, -2)], backend=backend) np.testing.assert_allclose(res, a.transpose() @ b)
def test_trace(backend): a = np.ones((2, 2)) res = ncon_interface.ncon([a], [(1, 1)], backend=backend) np.testing.assert_allclose(res, 2)
def test_output_order(backend): a = np.random.randn(2, 2) res = ncon_interface.ncon([a], [(-2, -1)], backend=backend) np.testing.assert_allclose(res, a.transpose())
def test_out_of_order_contraction(backend): a = np.ones((2, 2, 2)) with pytest.warns(UserWarning, match='Suboptimal ordering'): ncon_interface.ncon([a, a, a], [(-1, 1, 3), (1, 3, 2), (2, -2, -3)], backend=backend)
def test_invalid_network(self): a = tf.ones((2, 2)) with self.assertRaises(ValueError): ncon_interface.ncon([a, a], [(0, 1), (1, 0), (0, 1)]) with self.assertRaises(ValueError): ncon_interface.ncon([a, a], [(0, 1), (1, 1)]) with self.assertRaises(ValueError): ncon_interface.ncon([a, a], [(0, 1), (2, 0)]) with self.assertRaises(ValueError): ncon_interface.ncon([a, a], [(0, 1), (1, 0.1)]) with self.assertRaises(ValueError): ncon_interface.ncon([a, a], [(0, 1), (1, 't')]) with self.assertRaises(ValueError): ncon_interface.ncon([a, a], [(0,), (0, 1)])
def test_order_spec_noninteger(self): a = tf.ones((2, 2)) result = ncon_interface.ncon([a, a], [('o1', 'i'), ('i', 'o2')], con_order=['i'], out_order=['o1', 'o2']) self.assertAllClose(result, tf.ones((2, 2)) * 2)
def test_sanity_check(self): result = ncon_interface.ncon([tf.ones( (2, 2)), tf.ones((2, 2))], [(-1, 0), (0, -2)]) self.assertAllClose(result, tf.ones((2, 2)) * 2)
def test_contraction(self): a = np.random.randn(2, 2, 2) res = ncon_interface.ncon([a, a, a], [(-1, 0, 1), (0, 1, 2), (2, -2, -3)]) res_np = a.reshape((2, 4)) @ a.reshape((4, 2)) @ a.reshape((2, 4)) res_np = res_np.reshape((2, 2, 2)) self.assertAllClose(res, res_np)
def test_small_matmul(self): a = np.random.randn(2, 2) b = np.random.randn(2, 2) res = ncon_interface.ncon([a, b], [(0, -1), (0, -2)]) self.assertAllClose(res, a.transpose() @ b)
def test_out_of_order_contraction(self): a = tf.ones((2, 2, 2)) with self.assertRaises(ValueError): ncon_interface.ncon([a, a, a], [(-1, 0, 2), (0, 2, 1), (1, -2, -3)])
def test_sanity_check(backend): result = ncon_interface.ncon([np.ones( (2, 2)), np.ones((2, 2))], [(-1, 1), (1, -2)], backend=backend) np.testing.assert_allclose(result, np.ones((2, 2)) * 2)
def test_trace(self): a = tf.ones((2, 2)) res = ncon_interface.ncon([a], [(0, 0)]) self.assertEqual(res.numpy(), 2)
def test_invalid_network(backend): a = np.ones((2, 2)) with pytest.raises(ValueError): ncon_interface.ncon([a, a], [(1, 2), (2, 1), (1, 2)], backend=backend) with pytest.raises(ValueError): ncon_interface.ncon([a, a], [(1, 2), (2, 2)], backend=backend) with pytest.raises(ValueError): ncon_interface.ncon([a, a], [(1, 2), (3, 1)], backend=backend) with pytest.raises(ValueError): ncon_interface.ncon([a, a], [(1, 2), (2, 0.1)], backend=backend) with pytest.raises(ValueError): ncon_interface.ncon([a, a], [(1, 2), (2, 't')], backend=backend) with pytest.raises(ValueError): ncon_interface.ncon([a, a], [(0, 1), (1, 0)], backend=backend) with pytest.raises(ValueError): ncon_interface.ncon([a, a], [(1, ), (1, 2)], backend=backend)
def test_output_order(self): a = np.random.randn(2, 2) res = ncon_interface.ncon([a], [(-2, -1)]) self.assertAllClose(res, a.transpose())