def test_unsupported_operations(self): """Assert unsupported operations raise an error.""" cvar = CVaRMeasurement(Z) attrs = [ 'to_matrix', 'to_matrix_op', 'to_density_matrix', 'to_circuit_op', 'sample' ] for attr in attrs: with self.subTest(attr): with self.assertRaises(NotImplementedError): _ = getattr(cvar, attr)() with self.subTest('adjoint'): with self.assertRaises(OpflowError): cvar.adjoint()
def test_cvar_simple_with_coeff(self): """Test a simple case with a non-unity coefficient""" theta = 2.2 qc = QuantumCircuit(1) qc.ry(theta, 0) statefn = StateFn(qc) alpha = 0.2 cvar = ((-1 * CVaRMeasurement(Z, alpha)) @ statefn).eval() ref = self.expected_cvar(statefn.to_matrix(), Z, alpha) self.assertAlmostEqual(cvar, -1 * ref)
def test_cvar_on_paulisumop(self): """Test a large PauliSumOp is checked for diagonality efficiently. Regression test for Qiskit/qiskit-terra#7573. """ op = PauliSumOp.from_list([("Z" * 30, 1)]) # assert global algorithm settings do not have massive calculations turned on # -- which is the default, but better to be sure in the test! # also add a cleanup so we're sure to reset to the original value after the test, even if # the test would fail self.addCleanup(self.cleanup_algorithm_globals, algorithm_globals.massive) algorithm_globals.massive = False cvar = CVaRMeasurement(op, alpha=0.1) fake_probabilities = [0.2, 0.8] fake_energies = [1, 2] expectation = cvar.compute_cvar(fake_energies, fake_probabilities) self.assertEqual(expectation, 1)
def test_cvar_simple(self): """Test a simple case with a single Pauli.""" theta = 1.2 qc = QuantumCircuit(1) qc.ry(theta, 0) statefn = StateFn(qc) for alpha in [0.2, 0.4, 1]: with self.subTest(alpha=alpha): cvar = (CVaRMeasurement(Z, alpha) @ statefn).eval() ref = self.expected_cvar(statefn.to_matrix(), Z, alpha) self.assertAlmostEqual(cvar, ref)
def invalid_input(self): """Test invalid input raises an error.""" op = Z with self.subTest('alpha < 0'): with self.assertRaises(ValueError): _ = CVaRMeasurement(op, alpha=-0.2) with self.subTest('alpha > 1'): with self.assertRaises(ValueError): _ = CVaRMeasurement(op, alpha=12.3) with self.subTest('Single pauli operator not diagonal'): op = Y with self.assertRaises(OpflowError): _ = CVaRMeasurement(op) with self.subTest('Summed pauli operator not diagonal'): op = X ^ Z + Z ^ I with self.assertRaises(OpflowError): _ = CVaRMeasurement(op) with self.subTest('List operator not diagonal'): op = ListOp([X ^ Z, Z ^ I]) with self.assertRaises(OpflowError): _ = CVaRMeasurement(op) with self.subTest('Matrix operator not diagonal'): op = MatrixOp([[1, 1], [0, 1]]) with self.assertRaises(OpflowError): _ = CVaRMeasurement(op)
def test_construction(self): """Test the correct operator expression is constructed.""" alpha = 0.5 base_expecation = PauliExpectation() cvar_expecation = CVaRExpectation(alpha=alpha, expectation=base_expecation) with self.subTest('single operator'): op = ~StateFn(Z) @ Plus expected = CVaRMeasurement(Z, alpha) @ Plus cvar = cvar_expecation.convert(op) self.assertEqual(cvar, expected) with self.subTest('list operator'): op = ~StateFn(ListOp([Z ^ Z, I ^ Z])) @ (Plus ^ Plus) expected = ListOp([ CVaRMeasurement((Z ^ Z), alpha) @ (Plus ^ Plus), CVaRMeasurement((I ^ Z), alpha) @ (Plus ^ Plus) ]) cvar = cvar_expecation.convert(op) self.assertEqual(cvar, expected)
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_add(self): """Test addition.""" theta = 2.2 qc = QuantumCircuit(1) qc.ry(theta, 0) statefn = StateFn(qc) alpha = 0.2 cvar = -1 * CVaRMeasurement(Z, alpha) ref = self.expected_cvar(statefn.to_matrix(), Z, alpha) other = ~StateFn(I) # test add in both directions res1 = ((cvar + other) @ statefn).eval() res2 = ((other + other) @ statefn).eval() self.assertAlmostEqual(res1, 1 - ref) self.assertAlmostEqual(res2, 1 - ref)