def test_evolution_matrix_y1_zz(self): # make expr J20, J33 = sympy.symbols('J20 J33') y1 = pauli_product(2, 0) y1_as_gate = qutip.Qobj(y1.tolist(), dims=[[2] * 2] * 2) zz = pauli_product(3, 3) zz_as_gate = qutip.Qobj(zz.tolist(), dims=[[2] * 2] * 2) expr = J20 * y1 + J33 * zz some_hamiltonian = zz_as_gate + 1.3 * y1_as_gate some_target_gate = qutip.Qobj(scipy.linalg.expm( -1j * some_hamiltonian.full()), dims=[[2] * 2] * 2) # make net with random initial values model = QubitNetworkModel(sympy_expr=expr) # set the parameters in the hamiltonian to the correct values newJ = [0, 0] newJ[model.free_parameters.index(J33)] = 1. newJ[model.free_parameters.index(J20)] = 1.3 model.parameters.set_value(newJ) # compute evolution matrix with current (randomly generated) parameters evolution_matrix = theano.function([], model.compute_evolution_matrix())() # check evolution matrix assert_almost_equal(bigreal2complex(evolution_matrix), some_target_gate.full())
def test_grad_evolution2(self): """Test computation of grad of expm. Note: This test fails if theano is not patched to correct the gradient of expm """ J00, J11 = sympy.symbols('J00 J11') hamiltonian = J00 * pauli_product(0, 0) + J11 * pauli_product(1, 1) net = QubitNetworkModel(sympy_expr=hamiltonian) unitary_evolution = net.compute_evolution_matrix() grads_matrix = theano_matrix_grad(unitary_evolution, net.parameters) compute_grads = theano.function([], grads_matrix) args = [0, 0] net.parameters.set_value(args) grads0, grads1 = compute_grads() # manual gradient _compute_evol = theano.function([], unitary_evolution) def compute_evol(*args): net.parameters.set_value([*args]) return _compute_evol() eps = 0.00000001 manual_grad0 = (compute_evol(args[0] + eps, args[1]) - compute_evol(args[0], args[1])) / eps # compare results assert_almost_equal(grads0, manual_grad0)
def test_evolution_matrix_x1_xx(self): # Test the consistency of the output of `compute_evolution_matrix` # with the result obtained directly via `scipy.linalg.expm`. # build simple hamiltonian a, b = sympy.symbols('a, b') x1 = pauli_product(1, 0) xx = pauli_product(1, 1) expr = a * x1 + b * xx # make model with initially 0 values for interactions model = QubitNetworkModel(sympy_expr=expr, initial_values=0) compute_evolution = theano.function([], model.compute_evolution_matrix()) # check that if all parameters are zero evolution is the identity assert_array_equal(compute_evolution(), np.identity(8)) # set a=1, b=0 and check result newJ = [0, 0] newJ[model.free_parameters.index(a)] = 1 model.parameters.set_value(newJ) new_evolution = complex2bigreal( scipy.linalg.expm(-1j * np.asarray(x1).astype(np.complex))) assert_almost_equal(compute_evolution(), new_evolution) # try with a=1.3, b=-3. and check result newJ = [0, 0] newJ[model.free_parameters.index(a)] = 1.3 newJ[model.free_parameters.index(b)] = -3 model.parameters.set_value(newJ) new_evolution = complex2bigreal( scipy.linalg.expm( -1j * np.asarray(1.3 * x1 - 3 * xx).astype(np.complex))) assert_almost_equal(compute_evolution(), new_evolution)
def test_parse_from_sympy_expr(self): a, b = sympy.symbols('a, b') x1 = pauli_product(1, 0) xx = pauli_product(1, 1) expr = a * x1 + b * xx net = QubitNetwork(sympy_expr=expr) hamiltonian_matrix = net.get_matrix() self.assertListEqual( sympy.flatten(hamiltonian_matrix), sympy.flatten( sympy.Matrix([[0, 0, 1.0 * a, 1.0 * b], [0, 0, 1.0 * b, 1.0 * a], [1.0 * a, 1.0 * b, 0, 0], [1.0 * b, 1.0 * a, 0, 0]]))) self.assertEqual(net.num_qubits, 2)
def test_pauli_products(self): def to_numpy(sympy_obj): return np.asarray(sympy_obj.tolist(), dtype=np.complex) x1 = to_numpy(pauli_product(1, 0)) xx = to_numpy(pauli_product(1, 1)) y2 = to_numpy(pauli_product(0, 2)) yz = to_numpy(pauli_product(2, 3)) assert_array_equal( x1, [[0, 0, 1.0, 0], [0, 0, 0, 1.0], [1.0, 0, 0, 0], [0, 1.0, 0, 0]]) assert_array_equal( xx, [[0, 0, 0, 1.0], [0, 0, 1.0, 0], [0, 1.0, 0, 0], [1.0, 0, 0, 0]]) assert_array_equal( y2, [[0, -1j, 0, 0], [1j, 0, 0, 0], [0, 0, 0, -1j], [0, 0, 1j, 0]]) assert_array_equal( yz, [[0, 0, -1j, 0], [0, 0, 0, 1j], [1j, 0, 0, 0], [0, -1j, 0, 0]])
def test_fidelity_no_ptrace_y1_zz(self): J20, J33 = sympy.symbols('J20 J33') y1 = pauli_product(2, 0) zz = pauli_product(3, 3) expr = J20 * y1 + J33 * zz # make gate zz_as_gate = qutip.Qobj(zz.tolist(), dims=[[2] * 2] * 2) y1_as_gate = qutip.Qobj(y1.tolist(), dims=[[2] * 2] * 2) target_gate = zz_as_gate + 1.3 * y1_as_gate # create model, parameters initialied at random values model = QubitNetworkGateModel(sympy_expr=expr, target_gate=target_gate) # make random inputs and corresponding target outputs inputs, outputs = model.generate_training_states(10) # compute fidelity from theano functions to test fidelities = theano.function([], model.fidelity(return_mean=False), givens={ model.inputs: inputs, model.outputs: outputs })() # extract evolution matrix for given parameters evolution_matrix = theano.function([], model.compute_evolution_matrix())() evolution_matrix = bigreal2qobj(evolution_matrix) # make inputs and outputs into qutip objects, easier to handle inputs = [bigreal2qobj(input_) for input_ in inputs] outputs = [bigreal2qobj(output) for output in outputs] # compute actual outputs actual_outputs = [evolution_matrix * in_ for in_ in inputs] # recompute fidelities with qutip def fid(ket1, ket2): ket1 = ket1.data.toarray() ket2 = ket2.data.toarray() return np.abs(np.vdot(ket1, ket2))**2 fidelities_check = [ fid(out, actual_out) for out, actual_out in zip(outputs, actual_outputs) ] # check results are compatible assert_almost_equal(fidelities, fidelities_check)
def test_generation_training_states(self): J20, J33 = sympy.symbols('J20 J33') y1 = pauli_product(2, 0) zz = pauli_product(3, 3) expr = J20 * y1 + J33 * zz zz_as_gate = qutip.Qobj(zz.tolist(), dims=[[2] * 2] * 2) y1_as_gate = qutip.Qobj(y1.tolist(), dims=[[2] * 2] * 2) target_gate = zz_as_gate + 1.3 * y1_as_gate model = QubitNetworkGateModel(sympy_expr=expr, target_gate=target_gate) inputs, outputs = model.generate_training_states(6) self.assertEqual(inputs.shape[0], 6) self.assertEqual(outputs.shape[0], 6) self.assertEqual(inputs.shape[1], 2 * 2**2) qutip_dims = [[2] * 2, [1] * 2] for input_, output in zip(inputs, outputs): input_ = qutip.Qobj(bigreal2complex(input_), dims=qutip_dims) output = qutip.Qobj(bigreal2complex(output), dims=qutip_dims) assert_almost_equal((target_gate * input_).data.toarray(), output.data.toarray())
def test_optimizer_cost(self): J00, J11 = sympy.symbols('J00 J11') hamiltonian_model = pauli_product(0, 0) * J00 + pauli_product(1, 1) * J11 target_gate = qutip.Qobj(pauli_product(1, 1).tolist(), dims=[[2] * 2] * 2) model = QubitNetworkGateModel(sympy_expr=hamiltonian_model, target_gate=target_gate) optimizer = Optimizer(model) # set parameters to have evolution implement XX gate new_parameters = [0, 0] new_parameters[model.free_parameters.index(J11)] = np.pi / 2 optimizer.net.parameters.set_value(new_parameters) # check via optimizer.cost that |00> goes to |11> fidelity = theano.function( [], optimizer.cost, givens={ model.inputs: complex2bigreal([1, 0, 0, 0]).reshape((1, 8)), model.outputs: complex2bigreal([0, 0, 0, 1]).reshape((1, 8)) })() assert_almost_equal(fidelity, np.array(1))
def test_grad(self): J00, J11 = sympy.symbols('J00 J11') hamiltonian_model = pauli_product(0, 0) * J00 + pauli_product(1, 1) * J11 target_gate = qutip.Qobj(pauli_product(1, 1).tolist(), dims=[[2] * 2] * 2) model = QubitNetworkGateModel(sympy_expr=hamiltonian_model, initial_values=1) optimizer = Optimizer(model, target_gate=target_gate, learning_rate=1, decay_rate=0.01) optimizer.refill_training_data(sample_size=2) train_model = theano.function( [], optimizer.cost, updates=optimizer.updates, givens={ model.inputs: optimizer.vars['train_inputs'], model.outputs: optimizer.vars['train_outputs'] }) first_fid = train_model() second_fid = train_model() assert_array_less(first_fid, second_fid)