def test_permute_on_list_op(self): """Test if ListOp permute method is consistent with PrimitiveOps permute methods.""" op1 = (X ^ Y ^ Z).to_circuit_op() op2 = Z ^ X ^ Y # ComposedOp indices = [1, 2, 0] primitive_op = op1 @ op2 primitive_op_perm = primitive_op.permute(indices) # CircuitOp.permute composed_op = ComposedOp([op1, op2]) composed_op_perm = composed_op.permute(indices) # reduce the ListOp to PrimitiveOp to_primitive = composed_op_perm.oplist[0] @ composed_op_perm.oplist[1] # compare resulting PrimitiveOps equal = np.allclose(primitive_op_perm.to_matrix(), to_primitive.to_matrix()) self.assertTrue(equal) # TensoredOp indices = [3, 5, 4, 0, 2, 1] primitive_op = op1 ^ op2 primitive_op_perm = primitive_op.permute(indices) tensored_op = TensoredOp([op1, op2]) tensored_op_perm = tensored_op.permute(indices) # reduce the ListOp to PrimitiveOp composed_oplist = tensored_op_perm.oplist to_primitive = (composed_oplist[0] @ (composed_oplist[1].oplist[0] ^ composed_oplist[1].oplist[1]) @ composed_oplist[2]) # compare resulting PrimitiveOps equal = np.allclose(primitive_op_perm.to_matrix(), to_primitive.to_matrix()) self.assertTrue(equal) # SummedOp primitive_op = X ^ Y ^ Z summed_op = SummedOp([primitive_op]) indices = [1, 2, 0] primitive_op_perm = primitive_op.permute(indices) # PauliOp.permute summed_op_perm = summed_op.permute(indices) # reduce the ListOp to PrimitiveOp to_primitive = summed_op_perm.oplist[ 0] @ primitive_op @ summed_op_perm.oplist[2] # compare resulting PrimitiveOps equal = np.allclose(primitive_op_perm.to_matrix(), to_primitive.to_matrix()) self.assertTrue(equal)
def test_evals(self): """ evals test """ # TODO: Think about eval names self.assertEqual(Z.eval('0').eval('0'), 1) self.assertEqual(Z.eval('1').eval('0'), 0) self.assertEqual(Z.eval('0').eval('1'), 0) self.assertEqual(Z.eval('1').eval('1'), -1) self.assertEqual(X.eval('0').eval('0'), 0) self.assertEqual(X.eval('1').eval('0'), 1) self.assertEqual(X.eval('0').eval('1'), 1) self.assertEqual(X.eval('1').eval('1'), 0) self.assertEqual(Y.eval('0').eval('0'), 0) self.assertEqual(Y.eval('1').eval('0'), -1j) self.assertEqual(Y.eval('0').eval('1'), 1j) self.assertEqual(Y.eval('1').eval('1'), 0) with self.assertRaises(ValueError): Y.eval('11') with self.assertRaises(ValueError): (X ^ Y).eval('1111') with self.assertRaises(ValueError): Y.eval((X ^ X).to_matrix_op()) # Check that Pauli logic eval returns same as matrix logic self.assertEqual(PrimitiveOp(Z.to_matrix()).eval('0').eval('0'), 1) self.assertEqual(PrimitiveOp(Z.to_matrix()).eval('1').eval('0'), 0) self.assertEqual(PrimitiveOp(Z.to_matrix()).eval('0').eval('1'), 0) self.assertEqual(PrimitiveOp(Z.to_matrix()).eval('1').eval('1'), -1) self.assertEqual(PrimitiveOp(X.to_matrix()).eval('0').eval('0'), 0) self.assertEqual(PrimitiveOp(X.to_matrix()).eval('1').eval('0'), 1) self.assertEqual(PrimitiveOp(X.to_matrix()).eval('0').eval('1'), 1) self.assertEqual(PrimitiveOp(X.to_matrix()).eval('1').eval('1'), 0) self.assertEqual(PrimitiveOp(Y.to_matrix()).eval('0').eval('0'), 0) self.assertEqual(PrimitiveOp(Y.to_matrix()).eval('1').eval('0'), -1j) self.assertEqual(PrimitiveOp(Y.to_matrix()).eval('0').eval('1'), 1j) self.assertEqual(PrimitiveOp(Y.to_matrix()).eval('1').eval('1'), 0) pauli_op = Z ^ I ^ X ^ Y mat_op = PrimitiveOp(pauli_op.to_matrix()) full_basis = list(map(''.join, itertools.product('01', repeat=pauli_op.num_qubits))) for bstr1, bstr2 in itertools.product(full_basis, full_basis): # print('{} {} {} {}'.format(bstr1, bstr2, pauli_op.eval(bstr1, bstr2), # mat_op.eval(bstr1, bstr2))) np.testing.assert_array_almost_equal(pauli_op.eval(bstr1).eval(bstr2), mat_op.eval(bstr1).eval(bstr2)) gnarly_op = SummedOp([(H ^ I ^ Y).compose(X ^ X ^ Z).tensor(Z), PrimitiveOp(Operator.from_label('+r0I')), 3 * (X ^ CX ^ T)], coeff=3 + .2j) gnarly_mat_op = PrimitiveOp(gnarly_op.to_matrix()) full_basis = list(map(''.join, itertools.product('01', repeat=gnarly_op.num_qubits))) for bstr1, bstr2 in itertools.product(full_basis, full_basis): np.testing.assert_array_almost_equal(gnarly_op.eval(bstr1).eval(bstr2), gnarly_mat_op.eval(bstr1).eval(bstr2))
def test_trotter_qrte_qdrift(self, initial_state, expected_state): """Test for TrotterQRTE with QDrift.""" operator = SummedOp([X, Z]) time = 1 evolution_problem = EvolutionProblem(operator, time, initial_state) algorithm_globals.random_seed = 0 trotter_qrte = TrotterQRTE(product_formula=QDrift()) evolution_result = trotter_qrte.evolve(evolution_problem) np.testing.assert_equal(evolution_result.evolved_state.eval(), expected_state)
def test_bind_parameters_complex(self): """bind parameters with a complex value test""" th1 = Parameter("th1") th2 = Parameter("th2") operator = th1 * X + th2 * Y bound_operator = operator.bind_parameters({th1: 3j, th2: 2}) expected_bound_operator = SummedOp([3j * X, (2 + 0j) * Y]) self.assertEqual(bound_operator, expected_bound_operator)
def test_trotter_qrte_trotter_single_qubit(self, product_formula, expected_state): """Test for default TrotterQRTE on a single qubit.""" operator = SummedOp([X, Z]) initial_state = StateFn([1, 0]) time = 1 evolution_problem = EvolutionProblem(operator, time, initial_state) trotter_qrte = TrotterQRTE(product_formula=product_formula) evolution_result_state_circuit = trotter_qrte.evolve(evolution_problem).evolved_state np.testing.assert_equal(evolution_result_state_circuit.eval(), expected_state)
def test_add(self): """ add test """ pauli_sum = 3 * X + Y self.assertIsInstance(pauli_sum, PauliSumOp) expected = PauliSumOp(3.0 * SparsePauliOp(Pauli("X")) + SparsePauliOp(Pauli("Y"))) self.assertEqual(pauli_sum, expected) pauli_sum = X + Y summed_op = SummedOp([X, Y]) self.assertEqual(pauli_sum, summed_op)
def test_add(self): """add test""" pauli_sum = 3 * X + Y self.assertIsInstance(pauli_sum, PauliSumOp) expected = PauliSumOp(3.0 * SparsePauliOp(Pauli("X")) + SparsePauliOp(Pauli("Y"))) self.assertEqual(pauli_sum, expected) pauli_sum = X + Y summed_op = SummedOp([X, Y]) self.assertEqual(pauli_sum, summed_op) a = Parameter("a") b = Parameter("b") actual = a * PauliSumOp.from_list( [("X", 2)]) + b * PauliSumOp.from_list([("Y", 1)]) expected = SummedOp([ PauliSumOp.from_list([("X", 2)], a), PauliSumOp.from_list([("Y", 1)], b) ]) self.assertEqual(actual, expected)
def test_group_subops(self, is_summed_op): """grouper subroutine test""" paulis = (I ^ X) + (2 * X ^ X) + (3 * Z ^ Y) if is_summed_op: paulis = paulis.to_pauli_op() grouped_sum = AbelianGrouper.group_subops(paulis) self.assertEqual(len(grouped_sum), 2) with self.subTest("test group subops 1"): if is_summed_op: expected = SummedOp([ SummedOp([I ^ X, 2.0 * X ^ X], abelian=True), SummedOp([3.0 * Z ^ Y], abelian=True) ]) self.assertEqual(grouped_sum, expected) else: self.assertSetEqual( frozenset([ frozenset(grouped_sum[i].primitive.to_list()) for i in range(2) ]), frozenset({ frozenset({('ZY', 3)}), frozenset({('IX', 1), ('XX', 2)}) })) paulis = X + (2 * Y) + (3 * Z) if is_summed_op: paulis = paulis.to_pauli_op() grouped_sum = AbelianGrouper.group_subops(paulis) self.assertEqual(len(grouped_sum), 3) with self.subTest("test group subops 2"): if is_summed_op: self.assertEqual(grouped_sum, paulis) else: self.assertSetEqual( frozenset( sum([ grouped_sum[i].primitive.to_list() for i in range(3) ], [])), frozenset([('X', 1), ('Y', 2), ('Z', 3)]))
def test_coeffs(self): """ListOp.coeffs test""" sum1 = SummedOp([(0 + 1j) * X, (1 / np.sqrt(2) + 1j / np.sqrt(2)) * Z], 0.5).collapse_summands() self.assertAlmostEqual(sum1.coeffs[0], 0.5j) self.assertAlmostEqual(sum1.coeffs[1], (1 + 1j) / (2 * np.sqrt(2))) a_param = Parameter("a") b_param = Parameter("b") param_exp = ParameterExpression({ a_param: 1, b_param: 0 }, Symbol("a")**2 + Symbol("b")) sum2 = SummedOp([X, (1 / np.sqrt(2) - 1j / np.sqrt(2)) * Y], param_exp).collapse_summands() self.assertIsInstance(sum2.coeffs[0], ParameterExpression) self.assertIsInstance(sum2.coeffs[1], ParameterExpression) # Nested ListOp sum_nested = SummedOp([X, sum1]) self.assertRaises(TypeError, lambda: sum_nested.coeffs)
def test_summedop_pauli_evolution(self): """SummedOp[PauliOp] evolution test""" op = SummedOp([ (-1.052373245772859 * I ^ I), (0.39793742484318045 * I ^ Z), (0.18093119978423156 * X ^ X), (-0.39793742484318045 * Z ^ I), (-0.01128010425623538 * Z ^ Z), ]) evolution = EvolutionFactory.build(operator=op) # wf = (Pl^Pl) + (Ze^Ze) wf = ((np.pi / 2) * op).exp_i() @ CX @ (H ^ I) @ Zero mean = evolution.convert(wf) self.assertIsNotNone(mean)
def _remove_identity(pauli_sum): """Remove any identity operators from `pauli_sum`. Return the sum of the coefficients of the identities and the new operator. """ idcoeff = 0.0 ops = [] for op in pauli_sum: p = op.primitive if p.x.any() or p.z.any(): ops.append(op) else: idcoeff += op.coeff return idcoeff, SummedOp(ops)
def test_coder_operators(self): """Test runtime encoder and decoder for operators.""" x = Parameter("x") y = x + 1 qc = QuantumCircuit(1) qc.h(0) coeffs = np.array([1, 2, 3, 4, 5, 6]) table = PauliTable.from_labels( ["III", "IXI", "IYY", "YIZ", "XYZ", "III"]) op = (2.0 * I ^ I) z2_symmetries = Z2Symmetries( [Pauli("IIZI"), Pauli("ZIII")], [Pauli("IIXI"), Pauli("XIII")], [1, 3], [-1, 1]) isqrt2 = 1 / np.sqrt(2) sparse = scipy.sparse.csr_matrix([[0, isqrt2, 0, isqrt2]]) subtests = ( PauliSumOp(SparsePauliOp(Pauli("XYZX"), coeffs=[2]), coeff=3), PauliSumOp(SparsePauliOp(Pauli("XYZX"), coeffs=[1]), coeff=y), PauliSumOp(SparsePauliOp(Pauli("XYZX"), coeffs=[1 + 2j]), coeff=3 - 2j), PauliSumOp.from_list([("II", -1.052373245772859), ("IZ", 0.39793742484318045)]), PauliSumOp(SparsePauliOp(table, coeffs), coeff=10), MatrixOp(primitive=np.array([[0, -1j], [1j, 0]]), coeff=x), PauliOp(primitive=Pauli("Y"), coeff=x), CircuitOp(qc, coeff=x), EvolvedOp(op, coeff=x), TaperedPauliSumOp(SparsePauliOp(Pauli("XYZX"), coeffs=[2]), z2_symmetries), StateFn(qc, coeff=x), CircuitStateFn(qc, is_measurement=True), DictStateFn("1" * 3, is_measurement=True), VectorStateFn(np.ones(2**3, dtype=complex)), OperatorStateFn(CircuitOp(QuantumCircuit(1))), SparseVectorStateFn(sparse), Statevector([1, 0]), CVaRMeasurement(Z, 0.2), ComposedOp([(X ^ Y ^ Z), (Z ^ X ^ Y ^ Z).to_matrix_op()]), SummedOp([X ^ X * 2, Y ^ Y], 2), TensoredOp([(X ^ Y), (Z ^ I)]), (Z ^ Z) ^ (I ^ 2), ) for op in subtests: with self.subTest(op=op): encoded = json.dumps(op, cls=RuntimeEncoder) self.assertIsInstance(encoded, str) decoded = json.loads(encoded, cls=RuntimeDecoder) self.assertEqual(op, decoded)
def test_expand_on_list_op(self): """ Test if expanded ListOp has expected num_qubits. """ add_qubits = 3 # ComposedOp composed_op = ComposedOp([(X ^ Y ^ Z), (H ^ T), (Z ^ X ^ Y ^ Z).to_matrix_op()]) expanded = composed_op._expand_dim(add_qubits) self.assertEqual(composed_op.num_qubits + add_qubits, expanded.num_qubits) # TensoredOp tensored_op = TensoredOp([(X ^ Y), (Z ^ I)]) expanded = tensored_op._expand_dim(add_qubits) self.assertEqual(tensored_op.num_qubits + add_qubits, expanded.num_qubits) # SummedOp summed_op = SummedOp([(X ^ Y), (Z ^ I ^ Z)]) expanded = summed_op._expand_dim(add_qubits) self.assertEqual(summed_op.num_qubits + add_qubits, expanded.num_qubits)
def test_qdrift_summed_op(self): """QDrift test for SummedOp""" op = SummedOp([ (2 * Z ^ Z), (3 * X ^ X), (-4 * Y ^ Y), (0.5 * Z ^ I), ]) trotterization = QDrift().convert(op) self.assertGreater(len(trotterization.oplist), 150) last_coeff = None # Check that all types are correct and all coefficients are equals for op in trotterization.oplist: self.assertIsInstance(op, (EvolvedOp, CircuitOp)) if isinstance(op, EvolvedOp): if last_coeff: self.assertEqual(op.primitive.coeff, last_coeff) else: last_coeff = op.primitive.coeff
def test_trotter_qrte_trotter_single_qubit_aux_ops(self): """Test for default TrotterQRTE on a single qubit with auxiliary operators.""" operator = SummedOp([X, Z]) # LieTrotter with 1 rep aux_ops = [X, Y] initial_state = Zero time = 3 evolution_problem = EvolutionProblem(operator, time, initial_state, aux_ops) expected_evolved_state = VectorStateFn( Statevector([0.98008514 + 0.13970775j, 0.01991486 + 0.13970775j], dims=(2,)) ) expected_aux_ops_evaluated = [(0.078073, 0.0), (0.268286, 0.0)] expected_aux_ops_evaluated_qasm = [ (0.05799999999999995, 0.011161518713866855), (0.2495, 0.010826759383582883), ] for backend_name in self.backends_names_not_none: with self.subTest(msg=f"Test {backend_name} backend."): algorithm_globals.random_seed = 0 backend = self.backends_dict[backend_name] expectation = ExpectationFactory.build( operator=operator, backend=backend, ) trotter_qrte = TrotterQRTE(quantum_instance=backend, expectation=expectation) evolution_result = trotter_qrte.evolve(evolution_problem) np.testing.assert_equal( evolution_result.evolved_state.eval(), expected_evolved_state ) if backend_name == "qi_qasm": expected_aux_ops_evaluated = expected_aux_ops_evaluated_qasm np.testing.assert_array_almost_equal( evolution_result.aux_ops_evaluated, expected_aux_ops_evaluated )
def test_list_op_parameters(self): """Test that Parameters are stored correctly in a List Operator""" lam = Parameter("λ") phi = Parameter("φ") omega = Parameter("ω") mat_op = PrimitiveOp([[0, 1], [1, 0]], coeff=omega) qc = QuantumCircuit(1) qc.rx(phi, 0) qc_op = PrimitiveOp(qc) op1 = SummedOp([mat_op, qc_op]) params = [phi, omega] self.assertEqual(op1.parameters, set(params)) # check list nesting case op2 = PrimitiveOp([[1, 0], [0, -1]], coeff=lam) list_op = ListOp([op1, op2]) params.append(lam) self.assertEqual(list_op.parameters, set(params))
def test_summed_op_reduce(self): """Test SummedOp""" sum_op = (X ^ X * 2) + (Y ^ Y) # type: PauliSumOp sum_op = sum_op.to_pauli_op() # type: SummedOp[PauliOp] with self.subTest("SummedOp test 1"): self.assertEqual(sum_op.coeff, 1) self.assertListEqual([str(op.primitive) for op in sum_op], ["XX", "YY"]) self.assertListEqual([op.coeff for op in sum_op], [2, 1]) sum_op = (X ^ X * 2) + (Y ^ Y) sum_op += Y ^ Y sum_op = sum_op.to_pauli_op() # type: SummedOp[PauliOp] with self.subTest("SummedOp test 2-a"): self.assertEqual(sum_op.coeff, 1) self.assertListEqual([str(op.primitive) for op in sum_op], ["XX", "YY", "YY"]) self.assertListEqual([op.coeff for op in sum_op], [2, 1, 1]) sum_op = sum_op.collapse_summands() with self.subTest("SummedOp test 2-b"): self.assertEqual(sum_op.coeff, 1) self.assertListEqual([str(op.primitive) for op in sum_op], ["XX", "YY"]) self.assertListEqual([op.coeff for op in sum_op], [2, 2]) sum_op = (X ^ X * 2) + (Y ^ Y) sum_op += (Y ^ Y) + (X ^ X * 2) sum_op = sum_op.to_pauli_op() # type: SummedOp[PauliOp] with self.subTest("SummedOp test 3-a"): self.assertEqual(sum_op.coeff, 1) self.assertListEqual([str(op.primitive) for op in sum_op], ["XX", "YY", "YY", "XX"]) self.assertListEqual([op.coeff for op in sum_op], [2, 1, 1, 2]) sum_op = sum_op.reduce().to_pauli_op() with self.subTest("SummedOp test 3-b"): self.assertEqual(sum_op.coeff, 1) self.assertListEqual([str(op.primitive) for op in sum_op], ["XX", "YY"]) self.assertListEqual([op.coeff for op in sum_op], [4, 2]) sum_op = SummedOp([X ^ X * 2, Y ^ Y], 2) with self.subTest("SummedOp test 4-a"): self.assertEqual(sum_op.coeff, 2) self.assertListEqual([str(op.primitive) for op in sum_op], ["XX", "YY"]) self.assertListEqual([op.coeff for op in sum_op], [2, 1]) sum_op = sum_op.collapse_summands() with self.subTest("SummedOp test 4-b"): self.assertEqual(sum_op.coeff, 1) self.assertListEqual([str(op.primitive) for op in sum_op], ["XX", "YY"]) self.assertListEqual([op.coeff for op in sum_op], [4, 2]) sum_op = SummedOp([X ^ X * 2, Y ^ Y], 2) sum_op += Y ^ Y with self.subTest("SummedOp test 5-a"): self.assertEqual(sum_op.coeff, 1) self.assertListEqual([str(op.primitive) for op in sum_op], ["XX", "YY", "YY"]) self.assertListEqual([op.coeff for op in sum_op], [4, 2, 1]) sum_op = sum_op.collapse_summands() with self.subTest("SummedOp test 5-b"): self.assertEqual(sum_op.coeff, 1) self.assertListEqual([str(op.primitive) for op in sum_op], ["XX", "YY"]) self.assertListEqual([op.coeff for op in sum_op], [4, 3]) sum_op = SummedOp([X ^ X * 2, Y ^ Y], 2) sum_op += ((X ^ X) * 2 + (Y ^ Y)).to_pauli_op() with self.subTest("SummedOp test 6-a"): self.assertEqual(sum_op.coeff, 1) self.assertListEqual([str(op.primitive) for op in sum_op], ["XX", "YY", "XX", "YY"]) self.assertListEqual([op.coeff for op in sum_op], [4, 2, 2, 1]) sum_op = sum_op.collapse_summands() with self.subTest("SummedOp test 6-b"): self.assertEqual(sum_op.coeff, 1) self.assertListEqual([str(op.primitive) for op in sum_op], ["XX", "YY"]) self.assertListEqual([op.coeff for op in sum_op], [6, 3]) sum_op = SummedOp([X ^ X * 2, Y ^ Y], 2) sum_op += sum_op with self.subTest("SummedOp test 7-a"): self.assertEqual(sum_op.coeff, 1) self.assertListEqual([str(op.primitive) for op in sum_op], ["XX", "YY", "XX", "YY"]) self.assertListEqual([op.coeff for op in sum_op], [4, 2, 4, 2]) sum_op = sum_op.collapse_summands() with self.subTest("SummedOp test 7-b"): self.assertEqual(sum_op.coeff, 1) self.assertListEqual([str(op.primitive) for op in sum_op], ["XX", "YY"]) self.assertListEqual([op.coeff for op in sum_op], [8, 4]) sum_op = SummedOp([X ^ X * 2, Y ^ Y], 2) + SummedOp([X ^ X * 2, Z ^ Z], 3) with self.subTest("SummedOp test 8-a"): self.assertEqual(sum_op.coeff, 1) self.assertListEqual([str(op.primitive) for op in sum_op], ["XX", "YY", "XX", "ZZ"]) self.assertListEqual([op.coeff for op in sum_op], [4, 2, 6, 3]) sum_op = sum_op.collapse_summands() with self.subTest("SummedOp test 8-b"): self.assertEqual(sum_op.coeff, 1) self.assertListEqual([str(op.primitive) for op in sum_op], ["XX", "YY", "ZZ"]) self.assertListEqual([op.coeff for op in sum_op], [10, 2, 3]) sum_op = SummedOp([]) with self.subTest("SummedOp test 9"): self.assertEqual(sum_op.reduce(), sum_op) sum_op = ((Z + I) ^ Z) + (Z ^ X) with self.subTest("SummedOp test 10"): expected = SummedOp([ PauliOp(Pauli("ZZ")), PauliOp(Pauli("IZ")), PauliOp(Pauli("ZX")) ]) self.assertEqual(sum_op.to_pauli_op(), expected)
def test_summed_op_reduce(self): """Test SummedOp""" sum_op = (X ^ X * 2) + (Y ^ Y) # type: PauliSumOp sum_op = sum_op.to_pauli_op() # type: SummedOp[PauliOp] with self.subTest('SummedOp test 1'): self.assertEqual(sum_op.coeff, 1) self.assertListEqual([str(op.primitive) for op in sum_op], ['XX', 'YY']) self.assertListEqual([op.coeff for op in sum_op], [2, 1]) sum_op = (X ^ X * 2) + (Y ^ Y) sum_op += Y ^ Y sum_op = sum_op.to_pauli_op() # type: SummedOp[PauliOp] with self.subTest('SummedOp test 2-a'): self.assertEqual(sum_op.coeff, 1) self.assertListEqual([str(op.primitive) for op in sum_op], ['XX', 'YY', 'YY']) self.assertListEqual([op.coeff for op in sum_op], [2, 1, 1]) sum_op = sum_op.collapse_summands() with self.subTest('SummedOp test 2-b'): self.assertEqual(sum_op.coeff, 1) self.assertListEqual([str(op.primitive) for op in sum_op], ['XX', 'YY']) self.assertListEqual([op.coeff for op in sum_op], [2, 2]) sum_op = (X ^ X * 2) + (Y ^ Y) sum_op += (Y ^ Y) + (X ^ X * 2) sum_op = sum_op.to_pauli_op() # type: SummedOp[PauliOp] with self.subTest('SummedOp test 3-a'): self.assertEqual(sum_op.coeff, 1) self.assertListEqual([str(op.primitive) for op in sum_op], ['XX', 'YY', 'YY', 'XX']) self.assertListEqual([op.coeff for op in sum_op], [2, 1, 1, 2]) sum_op = sum_op.reduce().to_pauli_op() with self.subTest('SummedOp test 3-b'): self.assertEqual(sum_op.coeff, 1) self.assertListEqual([str(op.primitive) for op in sum_op], ['XX', 'YY']) self.assertListEqual([op.coeff for op in sum_op], [4, 2]) sum_op = SummedOp([X ^ X * 2, Y ^ Y], 2) with self.subTest('SummedOp test 4-a'): self.assertEqual(sum_op.coeff, 2) self.assertListEqual([str(op.primitive) for op in sum_op], ['XX', 'YY']) self.assertListEqual([op.coeff for op in sum_op], [2, 1]) sum_op = sum_op.collapse_summands() with self.subTest('SummedOp test 4-b'): self.assertEqual(sum_op.coeff, 1) self.assertListEqual([str(op.primitive) for op in sum_op], ['XX', 'YY']) self.assertListEqual([op.coeff for op in sum_op], [4, 2]) sum_op = SummedOp([X ^ X * 2, Y ^ Y], 2) sum_op += Y ^ Y with self.subTest('SummedOp test 5-a'): self.assertEqual(sum_op.coeff, 1) self.assertListEqual([str(op.primitive) for op in sum_op], ['XX', 'YY', 'YY']) self.assertListEqual([op.coeff for op in sum_op], [4, 2, 1]) sum_op = sum_op.collapse_summands() with self.subTest('SummedOp test 5-b'): self.assertEqual(sum_op.coeff, 1) self.assertListEqual([str(op.primitive) for op in sum_op], ['XX', 'YY']) self.assertListEqual([op.coeff for op in sum_op], [4, 3]) sum_op = SummedOp([X ^ X * 2, Y ^ Y], 2) sum_op += ((X ^ X) * 2 + (Y ^ Y)).to_pauli_op() with self.subTest('SummedOp test 6-a'): self.assertEqual(sum_op.coeff, 1) self.assertListEqual([str(op.primitive) for op in sum_op], ['XX', 'YY', 'XX', 'YY']) self.assertListEqual([op.coeff for op in sum_op], [4, 2, 2, 1]) sum_op = sum_op.collapse_summands() with self.subTest('SummedOp test 6-b'): self.assertEqual(sum_op.coeff, 1) self.assertListEqual([str(op.primitive) for op in sum_op], ['XX', 'YY']) self.assertListEqual([op.coeff for op in sum_op], [6, 3]) sum_op = SummedOp([X ^ X * 2, Y ^ Y], 2) sum_op += sum_op with self.subTest('SummedOp test 7-a'): self.assertEqual(sum_op.coeff, 1) self.assertListEqual([str(op.primitive) for op in sum_op], ['XX', 'YY', 'XX', 'YY']) self.assertListEqual([op.coeff for op in sum_op], [4, 2, 4, 2]) sum_op = sum_op.collapse_summands() with self.subTest('SummedOp test 7-b'): self.assertEqual(sum_op.coeff, 1) self.assertListEqual([str(op.primitive) for op in sum_op], ['XX', 'YY']) self.assertListEqual([op.coeff for op in sum_op], [8, 4]) sum_op = SummedOp([X ^ X * 2, Y ^ Y], 2) + SummedOp([X ^ X * 2, Z ^ Z], 3) with self.subTest('SummedOp test 8-a'): self.assertEqual(sum_op.coeff, 1) self.assertListEqual([str(op.primitive) for op in sum_op], ['XX', 'YY', 'XX', 'ZZ']) self.assertListEqual([op.coeff for op in sum_op], [4, 2, 6, 3]) sum_op = sum_op.collapse_summands() with self.subTest('SummedOp test 8-b'): self.assertEqual(sum_op.coeff, 1) self.assertListEqual([str(op.primitive) for op in sum_op], ['XX', 'YY', 'ZZ']) self.assertListEqual([op.coeff for op in sum_op], [10, 2, 3])
def test_to_pauli_op(self): """ test to_pauli_op method """ target = X + Y self.assertIsInstance(target, PauliSumOp) expected = SummedOp([X, Y]) self.assertEqual(target.to_pauli_op(), expected)
class TestTrotterQRTE(QiskitOpflowTestCase): """TrotterQRTE tests.""" def setUp(self): super().setUp() self.seed = 50 algorithm_globals.random_seed = self.seed backend_statevector = BasicAer.get_backend("statevector_simulator") backend_qasm = BasicAer.get_backend("qasm_simulator") self.quantum_instance = QuantumInstance( backend=backend_statevector, shots=1, seed_simulator=self.seed, seed_transpiler=self.seed, ) self.quantum_instance_qasm = QuantumInstance( backend=backend_qasm, shots=8000, seed_simulator=self.seed, seed_transpiler=self.seed, ) self.backends_dict = { "qi_sv": self.quantum_instance, "qi_qasm": self.quantum_instance_qasm, "b_sv": backend_statevector, "None": None, } self.backends_names = ["qi_qasm", "b_sv", "None", "qi_sv"] self.backends_names_not_none = ["qi_sv", "b_sv", "qi_qasm"] @data( ( None, VectorStateFn( Statevector([0.29192658 - 0.45464871j, 0.70807342 - 0.45464871j], dims=(2,)) ), ), ( SuzukiTrotter(), VectorStateFn(Statevector([0.29192658 - 0.84147098j, 0.0 - 0.45464871j], dims=(2,))), ), ) @unpack def test_trotter_qrte_trotter_single_qubit(self, product_formula, expected_state): """Test for default TrotterQRTE on a single qubit.""" operator = SummedOp([X, Z]) initial_state = StateFn([1, 0]) time = 1 evolution_problem = EvolutionProblem(operator, time, initial_state) trotter_qrte = TrotterQRTE(product_formula=product_formula) evolution_result_state_circuit = trotter_qrte.evolve(evolution_problem).evolved_state np.testing.assert_equal(evolution_result_state_circuit.eval(), expected_state) def test_trotter_qrte_trotter_single_qubit_aux_ops(self): """Test for default TrotterQRTE on a single qubit with auxiliary operators.""" operator = SummedOp([X, Z]) # LieTrotter with 1 rep aux_ops = [X, Y] initial_state = Zero time = 3 evolution_problem = EvolutionProblem(operator, time, initial_state, aux_ops) expected_evolved_state = VectorStateFn( Statevector([0.98008514 + 0.13970775j, 0.01991486 + 0.13970775j], dims=(2,)) ) expected_aux_ops_evaluated = [(0.078073, 0.0), (0.268286, 0.0)] expected_aux_ops_evaluated_qasm = [ (0.05799999999999995, 0.011161518713866855), (0.2495, 0.010826759383582883), ] for backend_name in self.backends_names_not_none: with self.subTest(msg=f"Test {backend_name} backend."): algorithm_globals.random_seed = 0 backend = self.backends_dict[backend_name] expectation = ExpectationFactory.build( operator=operator, backend=backend, ) trotter_qrte = TrotterQRTE(quantum_instance=backend, expectation=expectation) evolution_result = trotter_qrte.evolve(evolution_problem) np.testing.assert_equal( evolution_result.evolved_state.eval(), expected_evolved_state ) if backend_name == "qi_qasm": expected_aux_ops_evaluated = expected_aux_ops_evaluated_qasm np.testing.assert_array_almost_equal( evolution_result.aux_ops_evaluated, expected_aux_ops_evaluated ) @data( ( SummedOp([(X ^ Y), (Y ^ X)]), VectorStateFn( Statevector( [-0.41614684 + 0.0j, 0.0 + 0.0j, 0.0 + 0.0j, 0.90929743 + 0.0j], dims=(2, 2) ) ), ), ( (Z ^ Z) + (Z ^ I) + (I ^ Z), VectorStateFn( Statevector( [-0.9899925 - 0.14112001j, 0.0 + 0.0j, 0.0 + 0.0j, 0.0 + 0.0j], dims=(2, 2) ) ), ), ( Y ^ Y, VectorStateFn( Statevector( [0.54030231 + 0.0j, 0.0 + 0.0j, 0.0 + 0.0j, 0.0 + 0.84147098j], dims=(2, 2) ) ), ), ) @unpack def test_trotter_qrte_trotter_two_qubits(self, operator, expected_state): """Test for TrotterQRTE on two qubits with various types of a Hamiltonian.""" # LieTrotter with 1 rep initial_state = StateFn([1, 0, 0, 0]) evolution_problem = EvolutionProblem(operator, 1, initial_state) trotter_qrte = TrotterQRTE() evolution_result = trotter_qrte.evolve(evolution_problem) np.testing.assert_equal(evolution_result.evolved_state.eval(), expected_state) def test_trotter_qrte_trotter_two_qubits_with_params(self): """Test for TrotterQRTE on two qubits with a parametrized Hamiltonian.""" # LieTrotter with 1 rep initial_state = StateFn([1, 0, 0, 0]) w_param = Parameter("w") u_param = Parameter("u") params_dict = {w_param: 2.0, u_param: 3.0} operator = w_param * (Z ^ Z) / 2.0 + (Z ^ I) + u_param * (I ^ Z) / 3.0 time = 1 evolution_problem = EvolutionProblem( operator, time, initial_state, hamiltonian_value_dict=params_dict ) expected_state = VectorStateFn( Statevector([-0.9899925 - 0.14112001j, 0.0 + 0.0j, 0.0 + 0.0j, 0.0 + 0.0j], dims=(2, 2)) ) trotter_qrte = TrotterQRTE() evolution_result = trotter_qrte.evolve(evolution_problem) np.testing.assert_equal(evolution_result.evolved_state.eval(), expected_state) @data( ( Zero, VectorStateFn( Statevector([0.23071786 - 0.69436148j, 0.4646314 - 0.49874749j], dims=(2,)) ), ), ( QuantumCircuit(1).compose(ZGate(), [0]), VectorStateFn( Statevector([0.23071786 - 0.69436148j, 0.4646314 - 0.49874749j], dims=(2,)) ), ), ) @unpack def test_trotter_qrte_qdrift(self, initial_state, expected_state): """Test for TrotterQRTE with QDrift.""" operator = SummedOp([X, Z]) time = 1 evolution_problem = EvolutionProblem(operator, time, initial_state) algorithm_globals.random_seed = 0 trotter_qrte = TrotterQRTE(product_formula=QDrift()) evolution_result = trotter_qrte.evolve(evolution_problem) np.testing.assert_equal(evolution_result.evolved_state.eval(), expected_state) @data((Parameter("t"), {}), (None, {Parameter("x"): 2}), (None, None)) @unpack def test_trotter_qrte_trotter_errors(self, t_param, hamiltonian_value_dict): """Test TrotterQRTE with raising errors.""" operator = X * Parameter("t") + Z initial_state = Zero time = 1 algorithm_globals.random_seed = 0 trotter_qrte = TrotterQRTE() with assert_raises(ValueError): evolution_problem = EvolutionProblem( operator, time, initial_state, t_param=t_param, hamiltonian_value_dict=hamiltonian_value_dict, ) _ = trotter_qrte.evolve(evolution_problem)
def estimate( self, hamiltonian: OperatorBase, state_preparation: Optional[StateFn] = None, evolution: Optional[EvolutionBase] = None, bound: Optional[float] = None) -> HamiltonianPhaseEstimationResult: """Run the Hamiltonian phase estimation algorithm. Args: hamiltonian: A Hermitian operator. state_preparation: The ``StateFn`` to be prepared, whose eigenphase will be measured. If this parameter is omitted, no preparation circuit will be run and input state will be the all-zero state in the computational basis. evolution: An evolution converter that generates a unitary from ``hamiltonian``. If ``None``, then the default ``PauliTrotterEvolution`` is used. bound: An upper bound on the absolute value of the eigenvalues of ``hamiltonian``. If omitted, then ``hamiltonian`` must be a Pauli sum, or a ``PauliOp``, in which case a bound will be computed. If ``hamiltonian`` is a ``MatrixOp``, then ``bound`` may not be ``None``. The tighter the bound, the higher the resolution of computed phases. Returns: HamiltonianPhaseEstimationResult instance containing the result of the estimation and diagnostic information. Raises: ValueError: If ``bound`` is ``None`` and ``hamiltonian`` is not a Pauli sum, i.e. a ``PauliSumOp`` or a ``SummedOp`` whose terms are of type ``PauliOp``. TypeError: If ``evolution`` is not of type ``EvolutionBase``. """ if evolution is None: evolution = PauliTrotterEvolution() elif not isinstance(evolution, EvolutionBase): raise TypeError( f'Expecting type EvolutionBase, got {type(evolution)}') if isinstance(hamiltonian, PauliSumOp): hamiltonian = hamiltonian.to_pauli_op() elif isinstance(hamiltonian, PauliOp): hamiltonian = SummedOp([hamiltonian]) if isinstance(hamiltonian, SummedOp): # remove identitiy terms # The term propto the identity is removed from hamiltonian. # This is done for three reasons: # 1. Work around an unknown bug that otherwise causes the energies to be wrong in some # cases. # 2. Allow working with a simpler Hamiltonian, one with fewer terms. # 3. Tighten the bound on the eigenvalues so that the spectrum is better resolved, i.e. # occupies more of the range of values representable by the qubit register. # The coefficient of this term will be added to the eigenvalues. id_coefficient, hamiltonian_no_id = _remove_identity(hamiltonian) # get the rescaling object pe_scale = self._get_scale(hamiltonian_no_id, bound) # get the unitary unitary = self._get_unitary(hamiltonian_no_id, pe_scale, evolution) elif isinstance(hamiltonian, MatrixOp): if bound is None: raise ValueError( 'bound must be specified if Hermitian operator is MatrixOp' ) # Do not subtract an identity term from the matrix, so do not compensate. id_coefficient = 0.0 pe_scale = self._get_scale(hamiltonian, bound) unitary = self._get_unitary(hamiltonian, pe_scale, evolution) else: raise TypeError( f'Hermitian operator of type {type(hamiltonian)} not supported.' ) if state_preparation is not None: state_preparation = state_preparation.to_circuit_op().to_circuit() # run phase estimation phase_estimation_result = self._phase_estimation.estimate( unitary=unitary, state_preparation=state_preparation) return HamiltonianPhaseEstimationResult( phase_estimation_result=phase_estimation_result, id_coefficient=id_coefficient, phase_estimation_scale=pe_scale)