Esempio n. 1
0
 def test_equivalence_with_manual_dm_then_trace(self):
     with tf.device('cpu'):
         states = random_pure_states((1000, 2**8, 1))
         t_start1 = time.time()
         dms1 = trace(density_matrix(states), [4, 5, 6, 7]) # Trace 2 and 3
         t_start2 = time.time()
         dms2 = density_matrix(states, [0, 1, 2, 3])        # Get the dm of 0 and 1
         t_end = time.time()
         self.assertTrue(almost_equal(dms1, dms2))
         print('Method 1:', t_end - t_start1)
         print('Method 2:', t_end - t_start2)
         print('Abount 10x faster')
Esempio n. 2
0
    def test_non_last_qubits_trace(self):
        # Test trace for two conseg. non-last qubits
        state1 = tensor([s0, s1])
        state2 = tensor([(s0 + s1)/np.sqrt(2), (s0 - s1)/np.sqrt(2)])
        state = tensor([state1, state2])
        dm1 = trace(density_matrix(state), [0, 1])
        self.assertTrue(almost_equal(dm1, density_matrix(state2)))

        # Test trace for two separated non-last qubits
        state_test = tensor([s0, (s0 + s1)/np.sqrt(2)])
        dm2 = trace(density_matrix(state), [1, 3])
        self.assertTrue(almost_equal(dm2, density_matrix(state_test)))
Esempio n. 3
0
 def apply_u(theta):
     u_layer.thetas.assign([theta])
     new_states = u_layer.matrix() @ input_states
     new_states_dm = density_matrix(new_states, [0])
     out_shape = ((lin_size, ) * 8)
     P0 = new_states_dm[:, 0, 0]
     return tf.reshape(P0, out_shape)
Esempio n. 4
0
    def test_append_zeros(self):
        def naive_impl(states, n):
            tensor([states] + [s0] * n)

        states = random_pure_states((10, 2 ** 12, 1))
        states = append_zeros(states, 2)
        print(density_matrix(states))
Esempio n. 5
0
def layer2(state_w, dm_in, t4):
    dm_w = density_matrix(state_w)
    dm_in = tensor([dm_w, dm_in])
    # ndtotext_print(dm_in)
    # Remember this is a density matrix, so we must apply U on both sides
    U_layer2.thetas.assign([t4])
    U_matrix = U_layer2.matrix()
    dm_out = U_matrix @ dm_in @ tf.math.conj(U_matrix)
    return trace(dm_out, [1, 2, 3])
Esempio n. 6
0
def layer1(w1, w2, w3, x1, x2, x3, t1, t2, t3):
    state_1_in = tensor([w1, x1])
    state_2_in = tensor([w2, x2])
    state_3_in = tensor([w3, x3])
    state_in = tensor([state_1_in, state_2_in, state_3_in])
    U_layer1.thetas.assign([t1, t2, t3])
    state_out = U_layer1.matrix() @ state_in
    out_layer1 = density_matrix(state_out, [0, 4, 8])
    return out_layer1
Esempio n. 7
0
    def call(self, inputs, training=None, mask=None):
        x1, x2, x3 = inputs[..., 0, :, :], inputs[...,
                                                  1, :, :], inputs[...,
                                                                   2, :, :]
        state_1_in = tensor([self.w1, x1])
        state_2_in = tensor([self.w2, x2])
        state_3_in = tensor([self.w3, x3])
        state_in = tensor([state_1_in, state_2_in, state_3_in])
        state_out = self.U_layer1.matrix() @ state_in
        dm_out_layer1 = density_matrix(state_out, [0, 4, 8])

        dm_w = density_matrix(self.w4)
        dm_in = tensor([dm_w, dm_out_layer1])
        U_matrix = self.U_layer2.matrix()
        dm_out = U_matrix @ dm_in @ tf.math.conj(U_matrix)
        dm_output = trace(dm_out, [1, 2, 3])
        P0 = dm_output[..., 0, 0]
        return P0
Esempio n. 8
0
 def test_density_matrix_trace_from_state(self):
     with tf.device('cpu'):
         # This method can take 500 states of 2**12 at once!
         dm1 = density_matrix(self.states1, [0, 1])  # Density matrix of forst 10 qubits
         dm1_0 = density_matrix(self.states1[0], [0, 1])
         # This con only take ~40 states of 2**12 at once...
         dm2 = trace(density_matrix(self.states1), [2, 3])
         dm2_0 = trace(density_matrix(self.states1[0]), [2, 3])
         # print('dm')
         # ndtotext_print(density_matrix(self.states1))
         # print('dm1')
         # ndtotext_print(dm1)
         # print('dm1_0')
         # ndtotext_print(dm1_0)
         # print('dm2')
         # ndtotext_print(dm2)
         # print('dm2_0')
         # ndtotext_print(dm2_0)
         self.assertTrue(almost_equal(dm1[0], dm1_0, 1e-3), 'density_matrix mixes states!')
         self.assertTrue(almost_equal(dm2[0], dm2_0, 1e-3), 'trace->density_matrix mixes states!')
         self.assertTrue(almost_equal(dm1, dm2, 1e-3))
Esempio n. 9
0
 def naive_alg(a, b):
     sqrtm = tf.linalg.sqrtm
     dm_a = density_matrix(a)
     dm_b = density_matrix(b)
     result = tf.linalg.trace(sqrtm(sqrtm(dm_a) @ dm_b @ sqrtm(dm_a))) ** 2
     return tf.cast(result, float_type)
Esempio n. 10
0
 def call(self, y_true, y_pred):
     delta = density_matrix(y_true, self.subsystem) - density_matrix(
         y_pred, self.subsystem)
     result = tf.linalg.trace(
         tf.linalg.sqrtm(tf.linalg.adjoint(delta) @ delta)) / 2
     return tf.cast(tf.reduce_mean(result), float_type)