def test_aux_operator_std_dev(self): """Test actuall standard deviation of aux operators in non-zero case.""" wavefunction = self.ry_wavefunction vqe = VQE( ansatz=wavefunction, optimizer=SPSA(maxiter=300, last_avg=5), quantum_instance=self.qasm_simulator, ) # Go again with two auxiliary operators aux_op1 = PauliSumOp.from_list([("II", 2.0)]) aux_op2 = PauliSumOp.from_list([("II", 0.5), ("ZZ", 0.5), ("YY", 0.5), ("XX", -0.5)]) aux_ops = [aux_op1, aux_op2, None, 0] result = vqe.compute_minimum_eigenvalue(self.h2_op, aux_operators=aux_ops) self.assertAlmostEqual(result.eigenvalue.real, -1.8691994, places=6) self.assertEqual(len(result.aux_operator_eigenvalues), 4) # expectation values self.assertAlmostEqual(result.aux_operator_eigenvalues[0][0], 2, places=6) self.assertAlmostEqual(result.aux_operator_eigenvalues[1][0], 0.0019531, places=6) self.assertEqual(result.aux_operator_eigenvalues[2][0], 0.0) self.assertEqual(result.aux_operator_eigenvalues[3][0], 0.0) # standard deviations self.assertAlmostEqual(result.aux_operator_eigenvalues[0][1], 0.0) self.assertAlmostEqual(result.aux_operator_eigenvalues[1][1], 0.0214711) self.assertAlmostEqual(result.aux_operator_eigenvalues[2][1], 0.0) self.assertAlmostEqual(result.aux_operator_eigenvalues[3][1], 0.0)
def test_to_ising(self): """test to_ising""" with self.subTest("minimize"): # minimize: x + x * y # subject to: x, y \in {0, 1} q_p = QuadraticProgram("test") q_p.binary_var(name="x") q_p.binary_var(name="y") q_p.minimize(linear={"x": 1}, quadratic={("x", "y"): 1}) op, offset = to_ising(q_p) op_ref = PauliSumOp.from_list([("ZI", -0.25), ("IZ", -0.75), ("ZZ", 0.25)]) np.testing.assert_allclose(op.to_matrix(), op_ref.to_matrix()) self.assertAlmostEqual(offset, 0.75) with self.subTest("maximize"): # maximize: x + x * y # subject to: x, y \in {0, 1} q_p = QuadraticProgram("test") q_p.binary_var(name="x") q_p.binary_var(name="y") q_p.maximize(linear={"x": 1}, quadratic={("x", "y"): 1}) op, offset = to_ising(q_p) op_ref = PauliSumOp.from_list([("ZI", 0.25), ("IZ", 0.75), ("ZZ", -0.25)]) np.testing.assert_allclose(op.to_matrix(), op_ref.to_matrix()) self.assertAlmostEqual(offset, -0.75)
def test_mapping_for_single_op(self): """Test for single register operator.""" with self.subTest("test +"): op = FermionicOp("+", display_format="dense") expected = PauliSumOp.from_list([("X", 0.5), ("Y", -0.5j)]) self.assertEqual(JordanWignerMapper().map(op), expected) with self.subTest("test -"): op = FermionicOp("-", display_format="dense") expected = PauliSumOp.from_list([("X", 0.5), ("Y", 0.5j)]) self.assertEqual(JordanWignerMapper().map(op), expected) with self.subTest("test N"): op = FermionicOp("N", display_format="dense") expected = PauliSumOp.from_list([("I", 0.5), ("Z", -0.5)]) self.assertEqual(JordanWignerMapper().map(op), expected) with self.subTest("test E"): op = FermionicOp("E", display_format="dense") expected = PauliSumOp.from_list([("I", 0.5), ("Z", 0.5)]) self.assertEqual(JordanWignerMapper().map(op), expected) with self.subTest("test I"): op = FermionicOp("I", display_format="dense") expected = PauliSumOp.from_list([("I", 1)]) self.assertEqual(JordanWignerMapper().map(op), expected)
def number_operator(fer_op, mode_number=None): """Find the qubit operator for the number operator in bravyi_kitaev_fast representation. Args: fer_op (FermionicOperator): the fermionic operator in the second quantized form mode_number (int): index, it corresponds to the mode for which number operator is required. Returns: PauliSumOp: the qubit operator """ modes = fer_op.h1.modes edge_list = bravyi_kitaev_fast_edge_list(fer_op) num_qubits = edge_list.shape[1] num_operator = PauliSumOp.from_list([('I' * num_qubits, 1.0)]) if mode_number is None: for i in range(modes): num_operator -= edge_operator_bi(edge_list, i) num_operator += \ PauliSumOp.from_list([('I' * num_qubits, 1.0 * modes)]) else: num_operator += (PauliSumOp.from_list([('I' * num_qubits, 1.0)]) - edge_operator_bi(edge_list, mode_number)) num_operator = 0.5 * num_operator return num_operator
def test_is_hermitian(self): """Test is_hermitian method""" with self.subTest("True test"): target = PauliSumOp.from_list( [ ("II", -1.052373245772859), ("IZ", 0.39793742484318045), ("ZI", -0.39793742484318045), ("ZZ", -0.01128010425623538), ("XX", 0.18093119978423156), ] ) self.assertTrue(target.is_hermitian()) with self.subTest("False test"): target = PauliSumOp.from_list( [ ("II", -1.052373245772859), ("IZ", 0.39793742484318045j), ("ZI", -0.39793742484318045), ("ZZ", -0.01128010425623538), ("XX", 0.18093119978423156), ] ) self.assertFalse(target.is_hermitian())
def vacuum_operator(fer_op): """Use the stabilizers to find the vacuum state in bravyi_kitaev_fast. Args: fer_op (FermionicOperator): the fermionic operator in the second quantized form Returns: PauliSumOp: the qubit operator """ edge_list = bravyi_kitaev_fast_edge_list(fer_op) num_qubits = edge_list.shape[1] vac_operator = PauliSumOp.from_list([('I' * num_qubits, 1.0)]) graph = retworkx.PyGraph() graph.extend_from_edge_list(list(map(tuple, edge_list.transpose()))) stabs = np.asarray(retworkx.cycle_basis(graph)) for stab in stabs: a_op = PauliSumOp.from_list([('I' * num_qubits, 1.0)]) stab = np.asarray(stab) for i in range(np.size(stab)): a_op = a_op * edge_operator_aij(edge_list, stab[i], stab[(i + 1) % np.size(stab)]) * 1j # a_op.scaling_coeff(1j) a_op += PauliSumOp.from_list([('I' * num_qubits, 1.0)]) vac_operator = vac_operator * a_op * np.sqrt(2) # vac_operator.scaling_coeff() return vac_operator
def test_aux_operator_std_dev_pauli(self): """Test non-zero standard deviations of aux operators with PauliExpectation.""" wavefunction = self.ry_wavefunction vqd = VQD( ansatz=wavefunction, expectation=PauliExpectation(), initial_point=[ 1.70256666, -5.34843975, -0.39542903, 5.99477786, -2.74374986, -4.85284669, 0.2442925, -1.51638917, ], optimizer=COBYLA(maxiter=0), quantum_instance=self.qasm_simulator, ) # Go again with two auxiliary operators aux_op1 = PauliSumOp.from_list([("II", 2.0)]) aux_op2 = PauliSumOp.from_list([("II", 0.5), ("ZZ", 0.5), ("YY", 0.5), ("XX", -0.5)]) aux_ops = [aux_op1, aux_op2] result = vqd.compute_eigenvalues(self.h2_op, aux_operators=aux_ops) self.assertEqual(len(result.aux_operator_eigenvalues), 2) # expectation values self.assertAlmostEqual(result.aux_operator_eigenvalues[0][0][0], 2.0, places=1) self.assertAlmostEqual(result.aux_operator_eigenvalues[0][1][0], 0.0019531249999999445, places=1) # standard deviations self.assertAlmostEqual(result.aux_operator_eigenvalues[0][0][1], 0.0) self.assertAlmostEqual(result.aux_operator_eigenvalues[0][1][1], 0.015183867579396111, places=1) # Go again with additional None and zero operators aux_ops = [*aux_ops, None, 0] result = vqd.compute_eigenvalues(self.h2_op, aux_operators=aux_ops) self.assertEqual(len(result.aux_operator_eigenvalues[0]), 4) # expectation values self.assertAlmostEqual(result.aux_operator_eigenvalues[0][0][0], 2.0, places=1) self.assertAlmostEqual(result.aux_operator_eigenvalues[0][1][0], 0.0019531249999999445, places=1) self.assertEqual(result.aux_operator_eigenvalues[0][2][0], 0.0) self.assertEqual(result.aux_operator_eigenvalues[0][3][0], 0.0) # # standard deviations self.assertAlmostEqual(result.aux_operator_eigenvalues[0][0][1], 0.0) self.assertAlmostEqual(result.aux_operator_eigenvalues[0][1][1], 0.01548658094658011, places=1) self.assertAlmostEqual(result.aux_operator_eigenvalues[0][2][1], 0.0) self.assertAlmostEqual(result.aux_operator_eigenvalues[0][3][1], 0.0)
def test_opflow_qnn_2_2(self, q_i): """Test Torch Connector + Opflow QNN with input/output dimension 2/2.""" from torch import Tensor if q_i == "sv": quantum_instance = self._sv_quantum_instance else: quantum_instance = self._qasm_quantum_instance # construct parametrized circuit params_1 = [Parameter("input1"), Parameter("weight1")] qc_1 = QuantumCircuit(1) qc_1.h(0) qc_1.ry(params_1[0], 0) qc_1.rx(params_1[1], 0) qc_sfn_1 = StateFn(qc_1) # construct cost operator h_1 = StateFn(PauliSumOp.from_list([("Z", 1.0), ("X", 1.0)])) # combine operator and circuit to objective function op_1 = ~h_1 @ qc_sfn_1 # construct parametrized circuit params_2 = [Parameter("input2"), Parameter("weight2")] qc_2 = QuantumCircuit(1) qc_2.h(0) qc_2.ry(params_2[0], 0) qc_2.rx(params_2[1], 0) qc_sfn_2 = StateFn(qc_2) # construct cost operator h_2 = StateFn(PauliSumOp.from_list([("Z", 1.0), ("X", 1.0)])) # combine operator and circuit to objective function op_2 = ~h_2 @ qc_sfn_2 op = ListOp([op_1, op_2]) qnn = OpflowQNN( op, [params_1[0], params_2[0]], [params_1[1], params_2[1]], quantum_instance=quantum_instance, input_gradients=True, ) model = TorchConnector(qnn) test_data = [ Tensor([1]), Tensor([1, 2]), Tensor([[1], [2]]), Tensor([[1, 2], [3, 4]]), ] # test model self._validate_output_shape(model, test_data) if q_i == "sv": self._validate_backward_pass(model)
def test_opflow_qnn_2_2(self, config): """Test Opflow QNN with input/output dimension 2/2.""" q_i, input_grad_required = config if q_i == STATEVECTOR: quantum_instance = self.sv_quantum_instance elif q_i == QASM: quantum_instance = self.qasm_quantum_instance else: quantum_instance = None # construct parametrized circuit params_1 = [Parameter("input1"), Parameter("weight1")] qc_1 = QuantumCircuit(1) qc_1.h(0) qc_1.ry(params_1[0], 0) qc_1.rx(params_1[1], 0) qc_sfn_1 = StateFn(qc_1) # construct cost operator h_1 = StateFn(PauliSumOp.from_list([("Z", 1.0), ("X", 1.0)])) # combine operator and circuit to objective function op_1 = ~h_1 @ qc_sfn_1 # construct parametrized circuit params_2 = [Parameter("input2"), Parameter("weight2")] qc_2 = QuantumCircuit(1) qc_2.h(0) qc_2.ry(params_2[0], 0) qc_2.rx(params_2[1], 0) qc_sfn_2 = StateFn(qc_2) # construct cost operator h_2 = StateFn(PauliSumOp.from_list([("Z", 1.0), ("X", 1.0)])) # combine operator and circuit to objective function op_2 = ~h_2 @ qc_sfn_2 op = ListOp([op_1, op_2]) qnn = OpflowQNN( op, [params_1[0], params_2[0]], [params_1[1], params_2[1]], quantum_instance=quantum_instance, ) qnn.input_gradients = input_grad_required test_data = [np.array([1, 2]), np.array([[1, 2], [3, 4]])] # test model self.validate_output_shape(qnn, test_data) # test the qnn after we set a quantum instance if quantum_instance is None: qnn.quantum_instance = self.qasm_quantum_instance self.validate_output_shape(qnn, test_data)
def test_opflow_qnn_2_2(self, q_i): """ Test Torch Connector + Opflow QNN with input/output dimension 2/2.""" if q_i == 'sv': quantum_instance = self.sv_quantum_instance else: quantum_instance = self.qasm_quantum_instance # construct parametrized circuit params_1 = [Parameter('input1'), Parameter('weight1')] qc_1 = QuantumCircuit(1) qc_1.h(0) qc_1.ry(params_1[0], 0) qc_1.rx(params_1[1], 0) qc_sfn_1 = StateFn(qc_1) # construct cost operator h_1 = StateFn(PauliSumOp.from_list([('Z', 1.0), ('X', 1.0)])) # combine operator and circuit to objective function op_1 = ~h_1 @ qc_sfn_1 # construct parametrized circuit params_2 = [Parameter('input2'), Parameter('weight2')] qc_2 = QuantumCircuit(1) qc_2.h(0) qc_2.ry(params_2[0], 0) qc_2.rx(params_2[1], 0) qc_sfn_2 = StateFn(qc_2) # construct cost operator h_2 = StateFn(PauliSumOp.from_list([('Z', 1.0), ('X', 1.0)])) # combine operator and circuit to objective function op_2 = ~h_2 @ qc_sfn_2 op = ListOp([op_1, op_2]) qnn = OpflowQNN(op, [params_1[0], params_2[0]], [params_1[1], params_2[1]], quantum_instance=quantum_instance) try: model = TorchConnector(qnn) test_data = [ Tensor(1), Tensor([1, 2]), Tensor([[1], [2]]), Tensor([[1, 2], [3, 4]]) ] # test model self.validate_output_shape(model, test_data) if q_i == 'sv': self.validate_backward_pass(model) except MissingOptionalLibraryError as ex: self.skipTest(str(ex))
def test_aux_operators_list(self): """Test list-based aux_operators.""" wavefunction = self.ry_wavefunction vqe = VQE(ansatz=wavefunction, quantum_instance=self.statevector_simulator) # Start with an empty list result = vqe.compute_minimum_eigenvalue(self.h2_op, aux_operators=[]) self.assertAlmostEqual(result.eigenvalue.real, self.h2_energy, places=6) self.assertIsNone(result.aux_operator_eigenvalues) # Go again with two auxiliary operators aux_op1 = PauliSumOp.from_list([("II", 2.0)]) aux_op2 = PauliSumOp.from_list([("II", 0.5), ("ZZ", 0.5), ("YY", 0.5), ("XX", -0.5)]) aux_ops = [aux_op1, aux_op2] result = vqe.compute_minimum_eigenvalue(self.h2_op, aux_operators=aux_ops) self.assertAlmostEqual(result.eigenvalue.real, self.h2_energy, places=6) self.assertEqual(len(result.aux_operator_eigenvalues), 2) # expectation values self.assertAlmostEqual(result.aux_operator_eigenvalues[0][0], 2, places=6) self.assertAlmostEqual(result.aux_operator_eigenvalues[1][0], 0, places=6) # standard deviations self.assertAlmostEqual(result.aux_operator_eigenvalues[0][1], 0.0) self.assertAlmostEqual(result.aux_operator_eigenvalues[1][1], 0.0) # Go again with additional None and zero operators extra_ops = [*aux_ops, None, 0] result = vqe.compute_minimum_eigenvalue(self.h2_op, aux_operators=extra_ops) self.assertAlmostEqual(result.eigenvalue.real, self.h2_energy, places=6) self.assertEqual(len(result.aux_operator_eigenvalues), 4) # expectation values self.assertAlmostEqual(result.aux_operator_eigenvalues[0][0], 2, places=6) self.assertAlmostEqual(result.aux_operator_eigenvalues[1][0], 0, places=6) self.assertEqual(result.aux_operator_eigenvalues[2][0], 0.0) self.assertEqual(result.aux_operator_eigenvalues[3][0], 0.0) # standard deviations self.assertAlmostEqual(result.aux_operator_eigenvalues[0][1], 0.0) self.assertAlmostEqual(result.aux_operator_eigenvalues[1][1], 0.0) self.assertAlmostEqual(result.aux_operator_eigenvalues[2][1], 0.0) self.assertAlmostEqual(result.aux_operator_eigenvalues[3][1], 0.0)
def test_aux_operator_std_dev_aer_pauli(self): """Test non-zero standard deviations of aux operators with AerPauliExpectation.""" wavefunction = self.ry_wavefunction vqe = VQE( ansatz=wavefunction, expectation=AerPauliExpectation(), optimizer=COBYLA(maxiter=0), quantum_instance=QuantumInstance( backend=Aer.get_backend("qasm_simulator"), shots=1, seed_simulator=algorithm_globals.random_seed, seed_transpiler=algorithm_globals.random_seed, ), ) # Go again with two auxiliary operators aux_op1 = PauliSumOp.from_list([("II", 2.0)]) aux_op2 = PauliSumOp.from_list([("II", 0.5), ("ZZ", 0.5), ("YY", 0.5), ("XX", -0.5)]) aux_ops = [aux_op1, aux_op2] result = vqe.compute_minimum_eigenvalue(self.h2_op, aux_operators=aux_ops) self.assertEqual(len(result.aux_operator_eigenvalues), 2) # expectation values self.assertAlmostEqual(result.aux_operator_eigenvalues[0][0], 2.0, places=6) self.assertAlmostEqual(result.aux_operator_eigenvalues[1][0], 0.6698863565455391, places=6) # standard deviations self.assertAlmostEqual(result.aux_operator_eigenvalues[0][1], 0.0) self.assertAlmostEqual(result.aux_operator_eigenvalues[1][1], 0.0, places=6) # Go again with additional None and zero operators aux_ops = [*aux_ops, None, 0] result = vqe.compute_minimum_eigenvalue(self.h2_op, aux_operators=aux_ops) self.assertEqual(len(result.aux_operator_eigenvalues), 4) # expectation values self.assertAlmostEqual(result.aux_operator_eigenvalues[0][0], 2.0, places=6) self.assertAlmostEqual(result.aux_operator_eigenvalues[1][0], 0.6036400943063891, places=6) self.assertEqual(result.aux_operator_eigenvalues[2][0], 0.0) self.assertEqual(result.aux_operator_eigenvalues[3][0], 0.0) # standard deviations self.assertAlmostEqual(result.aux_operator_eigenvalues[0][1], 0.0) self.assertAlmostEqual(result.aux_operator_eigenvalues[1][1], 0.0, places=6) self.assertAlmostEqual(result.aux_operator_eigenvalues[2][1], 0.0) self.assertAlmostEqual(result.aux_operator_eigenvalues[3][1], 0.0)
def test_aux_operators_dict(self): """Test dict-based aux_operators.""" aux_op1 = PauliSumOp.from_list([("II", 2.0)]) aux_op2 = PauliSumOp.from_list([("II", 0.5), ("ZZ", 0.5), ("YY", 0.5), ("XX", -0.5)]) aux_ops = {"aux_op1": aux_op1, "aux_op2": aux_op2} algo = NumPyEigensolver() result = algo.compute_eigenvalues(operator=self.qubit_op, aux_operators=aux_ops) self.assertEqual(len(result.eigenvalues), 1) self.assertEqual(len(result.eigenstates), 1) self.assertEqual(result.eigenvalues.dtype, np.float64) self.assertAlmostEqual(result.eigenvalues[0], -1.85727503) self.assertEqual(len(result.aux_operator_eigenvalues), 1) self.assertEqual(len(result.aux_operator_eigenvalues[0]), 2) # expectation values self.assertAlmostEqual( result.aux_operator_eigenvalues[0]["aux_op1"][0], 2, places=6) self.assertAlmostEqual( result.aux_operator_eigenvalues[0]["aux_op2"][0], 0, places=6) # standard deviations self.assertAlmostEqual( result.aux_operator_eigenvalues[0]["aux_op1"][1], 0.0) self.assertAlmostEqual( result.aux_operator_eigenvalues[0]["aux_op2"][1], 0.0) # Go again with additional None and zero operators extra_ops = {**aux_ops, "None_operator": None, "zero_operator": 0} result = algo.compute_eigenvalues(operator=self.qubit_op, aux_operators=extra_ops) self.assertEqual(len(result.eigenvalues), 1) self.assertEqual(len(result.eigenstates), 1) self.assertEqual(result.eigenvalues.dtype, np.float64) self.assertAlmostEqual(result.eigenvalues[0], -1.85727503) self.assertEqual(len(result.aux_operator_eigenvalues), 1) self.assertEqual(len(result.aux_operator_eigenvalues[0]), 3) # expectation values self.assertAlmostEqual( result.aux_operator_eigenvalues[0]["aux_op1"][0], 2, places=6) self.assertAlmostEqual( result.aux_operator_eigenvalues[0]["aux_op2"][0], 0, places=6) self.assertEqual( result.aux_operator_eigenvalues[0]["zero_operator"][0], 0.0) self.assertTrue( "None_operator" not in result.aux_operator_eigenvalues[0].keys()) # standard deviations self.assertAlmostEqual( result.aux_operator_eigenvalues[0]["aux_op1"][1], 0.0) self.assertAlmostEqual( result.aux_operator_eigenvalues[0]["aux_op2"][1], 0.0) self.assertAlmostEqual( result.aux_operator_eigenvalues[0]["zero_operator"][1], 0.0)
def test_aux_operator_std_dev_pauli(self): """Test non-zero standard deviations of aux operators with PauliExpectation.""" wavefunction = self.ry_wavefunction vqe = VQE( ansatz=wavefunction, expectation=PauliExpectation(), optimizer=COBYLA(maxiter=0), quantum_instance=self.qasm_simulator, ) # Go again with two auxiliary operators aux_op1 = PauliSumOp.from_list([("II", 2.0)]) aux_op2 = PauliSumOp.from_list([("II", 0.5), ("ZZ", 0.5), ("YY", 0.5), ("XX", -0.5)]) aux_ops = [aux_op1, aux_op2] result = vqe.compute_minimum_eigenvalue(self.h2_op, aux_operators=aux_ops) self.assertEqual(len(result.aux_operator_eigenvalues), 2) # expectation values self.assertAlmostEqual(result.aux_operator_eigenvalues[0][0], 2.0, places=6) self.assertAlmostEqual(result.aux_operator_eigenvalues[1][0], 0.6796875, places=6) # standard deviations self.assertAlmostEqual(result.aux_operator_eigenvalues[0][1], 0.0) self.assertAlmostEqual(result.aux_operator_eigenvalues[1][1], 0.02534712219145965, places=6) # Go again with additional None and zero operators aux_ops = [*aux_ops, None, 0] result = vqe.compute_minimum_eigenvalue(self.h2_op, aux_operators=aux_ops) self.assertEqual(len(result.aux_operator_eigenvalues), 4) # expectation values self.assertAlmostEqual(result.aux_operator_eigenvalues[0][0], 2.0, places=6) self.assertAlmostEqual(result.aux_operator_eigenvalues[1][0], 0.57421875, places=6) self.assertEqual(result.aux_operator_eigenvalues[2][0], 0.0) self.assertEqual(result.aux_operator_eigenvalues[3][0], 0.0) # # standard deviations self.assertAlmostEqual(result.aux_operator_eigenvalues[0][1], 0.0) self.assertAlmostEqual(result.aux_operator_eigenvalues[1][1], 0.026562146577166837, places=6) self.assertAlmostEqual(result.aux_operator_eigenvalues[2][1], 0.0) self.assertAlmostEqual(result.aux_operator_eigenvalues[3][1], 0.0)
def setUp(self): super().setUp() self.qubit_op = PauliSumOp.from_list([ ("II", -1.052373245772859), ("ZI", 0.39793742484318045), ("IZ", -0.39793742484318045), ("ZZ", -0.01128010425623538), ("XX", 0.18093119978423156), ]) aux_op1 = PauliSumOp.from_list([("II", 2.0)]) aux_op2 = PauliSumOp.from_list([("II", 0.5), ("ZZ", 0.5), ("YY", 0.5), ("XX", -0.5)]) self.aux_ops = [aux_op1, aux_op2]
def test_aux_operators_list(self): """Test list-based aux_operators.""" aux_op1 = PauliSumOp.from_list([("II", 2.0)]) aux_op2 = PauliSumOp.from_list([("II", 0.5), ("ZZ", 0.5), ("YY", 0.5), ("XX", -0.5)]) aux_ops = [aux_op1, aux_op2] algo = NumPyEigensolver() result = algo.compute_eigenvalues(operator=self.qubit_op, aux_operators=aux_ops) self.assertEqual(len(result.eigenvalues), 1) self.assertEqual(len(result.eigenstates), 1) self.assertEqual(result.eigenvalues.dtype, np.float64) self.assertAlmostEqual(result.eigenvalues[0], -1.85727503) self.assertEqual(len(result.aux_operator_eigenvalues), 1) self.assertEqual(len(result.aux_operator_eigenvalues[0]), 2) # expectation values self.assertAlmostEqual(result.aux_operator_eigenvalues[0][0][0], 2, places=6) self.assertAlmostEqual(result.aux_operator_eigenvalues[0][1][0], 0, places=6) # standard deviations self.assertAlmostEqual(result.aux_operator_eigenvalues[0][0][1], 0.0) self.assertAlmostEqual(result.aux_operator_eigenvalues[0][1][1], 0.0) # Go again with additional None and zero operators extra_ops = [*aux_ops, None, 0] result = algo.compute_eigenvalues(operator=self.qubit_op, aux_operators=extra_ops) self.assertEqual(len(result.eigenvalues), 1) self.assertEqual(len(result.eigenstates), 1) self.assertEqual(result.eigenvalues.dtype, np.float64) self.assertAlmostEqual(result.eigenvalues[0], -1.85727503) self.assertEqual(len(result.aux_operator_eigenvalues), 1) self.assertEqual(len(result.aux_operator_eigenvalues[0]), 4) # expectation values self.assertAlmostEqual(result.aux_operator_eigenvalues[0][0][0], 2, places=6) self.assertAlmostEqual(result.aux_operator_eigenvalues[0][1][0], 0, places=6) self.assertIsNone(result.aux_operator_eigenvalues[0][2], None) self.assertEqual(result.aux_operator_eigenvalues[0][3][0], 0.0) # standard deviations self.assertAlmostEqual(result.aux_operator_eigenvalues[0][0][1], 0.0) self.assertAlmostEqual(result.aux_operator_eigenvalues[0][1][1], 0.0) self.assertEqual(result.aux_operator_eigenvalues[0][3][1], 0.0)
def test_opflow_qnn_2_2(self, q_i): """ Test Opflow QNN with input/output dimension 2/2.""" if q_i == 'sv': quantum_instance = self.sv_quantum_instance else: quantum_instance = self.qasm_quantum_instance # construct parametrized circuit params_1 = [Parameter('input1'), Parameter('weight1')] qc_1 = QuantumCircuit(1) qc_1.h(0) qc_1.ry(params_1[0], 0) qc_1.rx(params_1[1], 0) qc_sfn_1 = StateFn(qc_1) # construct cost operator h_1 = StateFn(PauliSumOp.from_list([('Z', 1.0), ('X', 1.0)])) # combine operator and circuit to objective function op_1 = ~h_1 @ qc_sfn_1 # construct parametrized circuit params_2 = [Parameter('input2'), Parameter('weight2')] qc_2 = QuantumCircuit(1) qc_2.h(0) qc_2.ry(params_2[0], 0) qc_2.rx(params_2[1], 0) qc_sfn_2 = StateFn(qc_2) # construct cost operator h_2 = StateFn(PauliSumOp.from_list([('Z', 1.0), ('X', 1.0)])) # combine operator and circuit to objective function op_2 = ~h_2 @ qc_sfn_2 op = ListOp([op_1, op_2]) qnn = OpflowQNN(op, [params_1[0], params_2[0]], [params_1[1], params_2[1]], quantum_instance=quantum_instance) test_data = [ np.array([1, 2]), np.array([[1, 2], [3, 4]]) ] # test model self.validate_output_shape(qnn, test_data)
def test_quadratic_program_element_when_loaded_from_source(self): """Test QuadraticProgramElement when QuadraticProgram is loaded from an external source""" with self.subTest("from_ising"): q_p = QuadraticProgram() q_p.from_ising(PauliSumOp.from_list([("IZ", 1), ("ZZ", 2)])) self.assertEqual(id(q_p.objective.quadratic_program), id(q_p)) for elem in q_p.variables: self.assertEqual(id(elem.quadratic_program), id(q_p)) for elem in q_p.linear_constraints: self.assertEqual(id(elem.quadratic_program), id(q_p)) for elem in q_p.quadratic_constraints: self.assertEqual(id(elem.quadratic_program), id(q_p)) try: lp_file = self.get_resource_path("test_quadratic_program.lp", "problems/resources") q_p = QuadraticProgram() q_p.read_from_lp_file(lp_file) self.assertEqual(id(q_p.objective.quadratic_program), id(q_p)) for elem in q_p.variables: self.assertEqual(id(elem.quadratic_program), id(q_p)) for elem in q_p.linear_constraints: self.assertEqual(id(elem.quadratic_program), id(q_p)) for elem in q_p.quadratic_constraints: self.assertEqual(id(elem.quadratic_program), id(q_p)) except RuntimeError as ex: self.fail(str(ex))
def test_with_two_qubit_reduction(self): """Test the VQE using TwoQubitReduction.""" qubit_op = PauliSumOp.from_list([ ("IIII", -0.8105479805373266), ("IIIZ", 0.17218393261915552), ("IIZZ", -0.22575349222402472), ("IZZI", 0.1721839326191556), ("ZZII", -0.22575349222402466), ("IIZI", 0.1209126326177663), ("IZZZ", 0.16892753870087912), ("IXZX", -0.045232799946057854), ("ZXIX", 0.045232799946057854), ("IXIX", 0.045232799946057854), ("ZXZX", -0.045232799946057854), ("ZZIZ", 0.16614543256382414), ("IZIZ", 0.16614543256382414), ("ZZZZ", 0.17464343068300453), ("ZIZI", 0.1209126326177663), ]) tapered_qubit_op = TwoQubitReduction(num_particles=2).convert(qubit_op) for simulator in [self.qasm_simulator, self.statevector_simulator]: with self.subTest(f"Test for {simulator}."): vqe = VQE( self.ry_wavefunction, SPSA(maxiter=300, last_avg=5), quantum_instance=simulator, ) result = vqe.compute_minimum_eigenvalue(tapered_qubit_op) energy = -1.868 if simulator == self.qasm_simulator else self.h2_energy self.assertAlmostEqual(result.eigenvalue.real, energy, places=2)
def test_from_ising2(self): """test to_from_ising 2""" # minimize: 1 - 2 * x1 - 2 * x2 + 4 * x1 * x2 # subject to: x, y \in {0, 1} op = PauliSumOp.from_list([("ZZ", 1)]) with self.subTest("linear: True"): q_p = from_ising(op, 0, linear=True) self.assertEqual(q_p.get_num_vars(), op.num_qubits) self.assertEqual(q_p.get_num_linear_constraints(), 0) self.assertEqual(q_p.get_num_quadratic_constraints(), 0) self.assertAlmostEqual(q_p.objective.constant, 1) np.testing.assert_array_almost_equal( q_p.objective.linear.to_array(), [-2, -2]) np.testing.assert_array_almost_equal( q_p.objective.quadratic.to_array(), [[0, 4], [0, 0]]) with self.subTest("linear: False"): q_p = from_ising(op, 0, linear=False) self.assertEqual(q_p.get_num_vars(), op.num_qubits) self.assertEqual(q_p.get_num_linear_constraints(), 0) self.assertEqual(q_p.get_num_quadratic_constraints(), 0) self.assertAlmostEqual(q_p.objective.constant, 1) np.testing.assert_array_almost_equal( q_p.objective.linear.to_array(), [0, 0]) np.testing.assert_array_almost_equal( q_p.objective.quadratic.to_array(), [[-2, 4], [0, -2]])
def get_operator(values: np.ndarray) -> Tuple[PauliSumOp, float]: """Construct the Hamiltonian for a given Partition instance. Given a list of numbers for the Number Partitioning problem, we construct the Hamiltonian described as a list of Pauli gates. Args: values: array of values. Returns: operator for the Hamiltonian and a constant shift for the obj function. """ n = len(values) # The Hamiltonian is: # \sum_{i,j=1,\dots,n} ij z_iz_j + \sum_{i=1,\dots,n} i^2 pauli_list = [] for i in range(n): for j in range(i): x_p = np.zeros(n, dtype=np.bool) z_p = np.zeros(n, dtype=np.bool) z_p[i] = True z_p[j] = True pauli_list.append([2. * values[i] * values[j], Pauli(z_p, x_p)]) opflow_list = [(pauli[1].to_label(), pauli[0]) for pauli in pauli_list] return PauliSumOp.from_list(opflow_list), sum(values * values)
def _build_single_hopping_operator( excitation: Tuple[Tuple[int, ...], Tuple[int, ...]], num_spin_orbitals: int, qubit_converter: QubitConverter, ) -> Tuple[PauliSumOp, List[bool]]: label = ["I"] * num_spin_orbitals for occ in excitation[0]: label[occ] = "+" for unocc in excitation[1]: label[unocc] = "-" fer_op = FermionicOp(("".join(label), 4.0**len(excitation[0]))) qubit_op: PauliSumOp = qubit_converter.convert_match(fer_op) z2_symmetries = qubit_converter.z2symmetries commutativities = [] if not z2_symmetries.is_empty(): for symmetry in z2_symmetries.symmetries: symmetry_op = PauliSumOp.from_list([(symmetry.to_label(), 1.0)]) commuting = qubit_op.primitive.table.commutes_with_all( symmetry_op.primitive.table) anticommuting = qubit_op.primitive.table.anticommutes_with_all( symmetry_op.primitive.table) if commuting != anticommuting: # only one of them is True if commuting: commutativities.append(True) elif anticommuting: commutativities.append(False) else: raise QiskitNatureError( "Symmetry {} is nor commute neither anti-commute " "to exciting operator.".format(symmetry.to_label())) return qubit_op, commutativities
def test_list_pauli_sum(self): """Test AerPauliExpectation for ListOp[PauliSumOp]""" test_op = ListOp([PauliSumOp.from_list([("XX", 1), ("ZI", 3), ("ZZ", 5)])]) observable = AerPauliExpectation().convert(~StateFn(test_op)) self.assertIsInstance(observable, ListOp) self.assertIsInstance(observable[0], CircuitStateFn) self.assertTrue(observable[0].is_measurement)
def test_from_ising(self): """test to_from_ising""" # minimize: x + x * y # subject to: x, y \in {0, 1} op = PauliSumOp.from_list([("ZI", -0.25), ("IZ", -0.75), ("ZZ", 0.25)]) with self.subTest("linear: True"): q_p = from_ising(op, 0.75, linear=True) self.assertEqual(q_p.get_num_vars(), op.num_qubits) self.assertEqual(q_p.get_num_linear_constraints(), 0) self.assertEqual(q_p.get_num_quadratic_constraints(), 0) self.assertAlmostEqual(q_p.objective.constant, 0) np.testing.assert_array_almost_equal( q_p.objective.linear.to_array(), [1, 0]) np.testing.assert_array_almost_equal( q_p.objective.quadratic.to_array(), [[0, 1], [0, 0]]) with self.subTest("linear: False"): q_p = from_ising(op, 0.75, linear=False) self.assertEqual(q_p.get_num_vars(), op.num_qubits) self.assertEqual(q_p.get_num_linear_constraints(), 0) self.assertEqual(q_p.get_num_quadratic_constraints(), 0) self.assertAlmostEqual(q_p.objective.constant, 0) np.testing.assert_array_almost_equal( q_p.objective.linear.to_array(), [0, 0]) np.testing.assert_array_almost_equal( q_p.objective.quadratic.to_array(), [[1, 1], [0, 0]])
def mixer_operator(self): """Returns an optional mixer operator expressed as an operator or a quantum circuit. Returns: OperatorBase or QuantumCircuit, optional: mixer operator or circuit. """ if self._mixer is not None: return self._mixer # if no mixer is passed and we know the number of qubits, then initialize it. if self.cost_operator is not None: # local imports to avoid circular imports from qiskit.opflow import PauliSumOp num_qubits = self.cost_operator.num_qubits # Mixer is just a sum of single qubit X's on each qubit. Evolving by this operator # will simply produce rx's on each qubit. mixer_terms = [("I" * left + "X" + "I" * (num_qubits - left - 1), 1) for left in range(num_qubits)] mixer = PauliSumOp.from_list(mixer_terms) return mixer # otherwise we cannot provide a default return None
def _symmetry_reduce(self, qubit_ops: List[PauliSumOp], suppress_none: bool) -> List[Optional[PauliSumOp]]: if self._z2symmetries is None or self._z2symmetries.is_empty(): tapered_qubit_ops = qubit_ops else: logger.debug("Checking operators commute with symmetry:") symmetry_ops = [] for symmetry in self._z2symmetries.symmetries: symmetry_ops.append( PauliSumOp.from_list([(symmetry.to_label(), 1.0)])) commuted = [] for i, qubit_op in enumerate(qubit_ops): commutes = QubitConverter._check_commutes( symmetry_ops, qubit_op) commuted.append(commutes) logger.debug("Qubit operators commuted with symmetry %s", commuted) # Tapering values were set from prior convert so we go ahead and taper operators tapered_qubit_ops = [] for i, commutes in enumerate(commuted): if commutes: tapered_qubit_ops.append( self._z2symmetries.taper(qubit_ops[i])) elif not suppress_none: tapered_qubit_ops.append(None) return tapered_qubit_ops
def test_taper_empty_operator(self): """Test tapering of empty operator""" z2_symmetries = Z2Symmetries( symmetries=[Pauli("IIZI"), Pauli("IZIZ"), Pauli("ZIII")], sq_paulis=[Pauli("IIXI"), Pauli("IIIX"), Pauli("XIII")], sq_list=[1, 0, 3], tapering_values=[1, -1, -1], ) empty_op = PauliSumOp.from_list([("IIII", 0.0)]) tapered_op = z2_symmetries.taper(empty_op) expected_op = PauliSumOp.from_list([("I", 0.0)]) self.assertEqual(tapered_op, expected_op)
def _get_operator(self, weight_matrix): """Generate Hamiltonian for the max-cut problem of a graph. Args: weight_matrix (numpy.ndarray) : adjacency matrix. Returns: PauliSumOp: operator for the Hamiltonian float: a constant shift for the obj function. """ num_nodes = weight_matrix.shape[0] pauli_list = [] shift = 0 for i in range(num_nodes): for j in range(i): if weight_matrix[i, j] != 0: x_p = np.zeros(num_nodes, dtype=bool) z_p = np.zeros(num_nodes, dtype=bool) z_p[i] = True z_p[j] = True pauli_list.append( [0.5 * weight_matrix[i, j], Pauli((z_p, x_p))]) shift -= 0.5 * weight_matrix[i, j] opflow_list = [(pauli[1].to_label(), pauli[0]) for pauli in pauli_list] return PauliSumOp.from_list(opflow_list), shift
def test_find_Z2_symmetries(self): """test for find_Z2_symmetries""" qubit_op = PauliSumOp.from_list([ ("II", -1.0537076071291125), ("IZ", 0.393983679438514), ("ZI", -0.39398367943851387), ("ZZ", -0.01123658523318205), ("XX", 0.1812888082114961), ]) z2_symmetries = Z2Symmetries.find_Z2_symmetries(qubit_op) self.assertEqual(z2_symmetries.symmetries, [Pauli("ZZ")]) self.assertEqual(z2_symmetries.sq_paulis, [Pauli("IX")]) self.assertEqual(z2_symmetries.sq_list, [0]) self.assertEqual(z2_symmetries.tapering_values, None) tapered_op = z2_symmetries.taper(qubit_op)[1] self.assertEqual(tapered_op.z2_symmetries.symmetries, [Pauli("ZZ")]) self.assertEqual(tapered_op.z2_symmetries.sq_paulis, [Pauli("IX")]) self.assertEqual(tapered_op.z2_symmetries.sq_list, [0]) self.assertEqual(tapered_op.z2_symmetries.tapering_values, [-1]) z2_symmetries.tapering_values = [-1] primitive = SparsePauliOp.from_list([ ("I", -1.0424710218959303), ("Z", -0.7879673588770277), ("X", -0.18128880821149604), ]) expected_op = TaperedPauliSumOp(primitive, z2_symmetries) self.assertEqual(tapered_op, expected_op)
def setUp(self): super().setUp() self.ansatz = RealAmplitudes(num_qubits=2, reps=2) self.observable = PauliSumOp.from_list([ ("II", -1.052373245772859), ("IZ", 0.39793742484318045), ("ZI", -0.39793742484318045), ("ZZ", -0.01128010425623538), ("XX", 0.18093119978423156), ]) self.expvals = -1.0284380963435145, -1.284366511861733 self.psi = (RealAmplitudes(num_qubits=2, reps=2), RealAmplitudes(num_qubits=2, reps=3)) self.params = tuple(psi.parameters for psi in self.psi) self.hamiltonian = ( SparsePauliOp.from_list([("II", 1), ("IZ", 2), ("XI", 3)]), SparsePauliOp.from_list([("IZ", 1)]), SparsePauliOp.from_list([("ZI", 1), ("ZZ", 1)]), ) self.theta = ( [0, 1, 1, 2, 3, 5], [0, 1, 1, 2, 3, 5, 8, 13], [1, 2, 3, 4, 5, 6], )