def test_log_i(self): """ MatrixOp.log_i() test """ op = (-1.052373245772859 * I ^ I) + \ (0.39793742484318045 * I ^ Z) + \ (0.18093119978423156 * X ^ X) + \ (-0.39793742484318045 * Z ^ I) + \ (-0.01128010425623538 * Z ^ Z) * np.pi/2 # Test with CircuitOp log_exp_op = op.to_matrix_op().exp_i().log_i().to_pauli_op() np.testing.assert_array_almost_equal(op.to_matrix(), log_exp_op.to_matrix()) # Test with MatrixOp log_exp_op = op.to_matrix_op().exp_i().to_matrix_op().log_i().to_pauli_op() np.testing.assert_array_almost_equal(op.to_matrix(), log_exp_op.to_matrix()) # Test with PauliOp log_exp_op = op.to_matrix_op().exp_i().to_pauli_op().log_i().to_pauli_op() np.testing.assert_array_almost_equal(op.to_matrix(), log_exp_op.to_matrix()) # Test with EvolvedOp log_exp_op = op.exp_i().to_pauli_op().log_i().to_pauli_op() np.testing.assert_array_almost_equal(op.to_matrix(), log_exp_op.to_matrix()) # Test with proper ListOp op = ListOp([(0.39793742484318045 * I ^ Z), (0.18093119978423156 * X ^ X), (-0.39793742484318045 * Z ^ I), (-0.01128010425623538 * Z ^ Z) * np.pi / 2]) log_exp_op = op.to_matrix_op().exp_i().to_matrix_op().log_i().to_pauli_op() np.testing.assert_array_almost_equal(op.to_matrix(), log_exp_op.to_matrix())
def test_not_to_matrix_called(self): """45 qubit calculation - literally will not work if to_matrix is somehow called (in addition to massive=False throwing an error)""" qs = 45 states_op = ListOp([Zero ^ qs, One ^ qs, (Zero ^ qs) + (One ^ qs)]) paulis_op = ListOp([Z ^ qs, (I ^ Z ^ I) ^ int(qs / 3)]) converted_meas = self.expect.convert(~StateFn(paulis_op) @ states_op) np.testing.assert_array_almost_equal(converted_meas.eval(), [[1, -1, 0], [1, -1, 0]])
def test_list_op_eval_coeff_with_nonlinear_combofn(self): """Test evaluating a ListOp with non-linear combo function works with coefficients.""" state = One op = ListOp(5 * [I], coeff=2, combo_fn=numpy.prod) expr1 = ~StateFn(op) @ state expr2 = ListOp(5 * [~state @ I @ state], coeff=2, combo_fn=numpy.prod) self.assertEqual(expr1.eval(), 2) # if the coeff is propagated too far the result is 4 self.assertEqual(expr2.eval(), 2)
def test_pauli_expect_op_vector_state_vector(self): """pauli expect op vector state vector test""" paulis_op = ListOp([X, Y, Z, I]) states_op = ListOp([One, Zero, Plus, Minus]) valids = [[+0, 0, 1, -1], [+0, 0, 0, 0], [-1, 1, 0, -0], [+1, 1, 1, 1]] converted_meas = self.expect.convert(~StateFn(paulis_op) @ states_op) np.testing.assert_array_almost_equal(converted_meas.eval(), valids, decimal=1) sampled = self.sampler.convert(converted_meas) np.testing.assert_array_almost_equal(sampled.eval(), valids, decimal=1)
def _eval_aux_ops( self, parameters: np.ndarray, aux_operators: ListOrDict[OperatorBase], expectation: ExpectationBase, threshold: float = 1e-12, ) -> ListOrDict[Tuple[complex, complex]]: # Create new CircuitSampler to avoid breaking existing one's caches. sampler = CircuitSampler(self.quantum_instance) if isinstance(aux_operators, dict): list_op = ListOp(list(aux_operators.values())) else: list_op = ListOp(aux_operators) aux_op_meas = expectation.convert(StateFn(list_op, is_measurement=True)) aux_op_expect = aux_op_meas.compose( CircuitStateFn(self.ansatz.bind_parameters(parameters))) aux_op_expect_sampled = sampler.convert(aux_op_expect) # compute means values = np.real(aux_op_expect_sampled.eval()) # compute standard deviations variances = np.real( expectation.compute_variance(aux_op_expect_sampled)) if not isinstance(variances, np.ndarray) and variances == 0.0: # when `variances` is a single value equal to 0., our expectation value is exact and we # manually ensure the variances to be a list of the correct length variances = np.zeros(len(aux_operators), dtype=float) std_devs = np.sqrt(variances / self.quantum_instance.run_config.shots) # Discard values below threshold aux_op_means = values * (np.abs(values) > threshold) # zip means and standard deviations into tuples aux_op_results = zip(aux_op_means, std_devs) # Return None eigenvalues for None operators if aux_operators is a list. # None operators are already dropped in compute_minimum_eigenvalue if aux_operators is a dict. if isinstance(aux_operators, list): aux_operator_eigenvalues = [None] * len(aux_operators) key_value_iterator = enumerate(aux_op_results) else: aux_operator_eigenvalues = {} key_value_iterator = zip(aux_operators.keys(), aux_op_results) for key, value in key_value_iterator: if aux_operators[key] is not None: aux_operator_eigenvalues[key] = value return aux_operator_eigenvalues
def test_listop_num_qubits(self): """Test that ListOp.num_qubits checks that all operators have the same number of qubits.""" op = ListOp([X ^ Y, Y ^ Z]) with self.subTest("All operators have the same numbers of qubits"): self.assertEqual(op.num_qubits, 2) op = ListOp([X ^ Y, Y]) with self.subTest("Operators have different numbers of qubits"): with self.assertRaises(ValueError): op.num_qubits # pylint: disable=pointless-statement with self.assertRaises(ValueError): X @ op # pylint: disable=pointless-statement
def test_ibmq_grouped_pauli_expectation(self): """pauli expect op vector state vector test""" from qiskit import IBMQ p = IBMQ.load_account() backend = p.get_backend("ibmq_qasm_simulator") q_instance = QuantumInstance(backend, seed_simulator=self.seed, seed_transpiler=self.seed) paulis_op = ListOp([X, Y, Z, I]) states_op = ListOp([One, Zero, Plus, Minus]) valids = [[+0, 0, 1, -1], [+0, 0, 0, 0], [-1, 1, 0, -0], [+1, 1, 1, 1]] converted_meas = self.expect.convert(~StateFn(paulis_op) @ states_op) sampled = CircuitSampler(q_instance).convert(converted_meas) np.testing.assert_array_almost_equal(sampled.eval(), valids, decimal=1)
def test_summedop_equals(self): """Test SummedOp.equals""" ops = [Z, CircuitOp(ZGate()), MatrixOp([[1, 0], [0, -1]]), Zero, Minus] sum_op = sum(ops + [ListOp(ops)]) self.assertEqual(sum_op, sum_op) self.assertEqual(sum_op + sum_op, 2 * sum_op) self.assertEqual(sum_op + sum_op + sum_op, 3 * sum_op) ops2 = [Z, CircuitOp(ZGate()), MatrixOp([[1, 0], [0, 1]]), Zero, Minus] sum_op2 = sum(ops2 + [ListOp(ops)]) self.assertNotEqual(sum_op, sum_op2) self.assertEqual(sum_op2, sum_op2) sum_op3 = sum(ops) self.assertNotEqual(sum_op, sum_op3) self.assertNotEqual(sum_op2, sum_op3) self.assertEqual(sum_op3, sum_op3)
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_parameter_binding_on_listop(self): """Test passing a ListOp with differing parameters works with the circuit sampler.""" try: from qiskit.providers.aer import Aer except Exception as ex: # pylint: disable=broad-except self.skipTest( "Aer doesn't appear to be installed. Error: '{}'".format( str(ex))) return x, y = Parameter('x'), Parameter('y') circuit1 = QuantumCircuit(1) circuit1.p(0.2, 0) circuit2 = QuantumCircuit(1) circuit2.p(x, 0) circuit3 = QuantumCircuit(1) circuit3.p(y, 0) bindings = {x: -0.4, y: 0.4} listop = ListOp( [StateFn(circuit) for circuit in [circuit1, circuit2, circuit3]]) sampler = CircuitSampler(Aer.get_backend('qasm_simulator')) sampled = sampler.convert(listop, params=bindings) self.assertTrue(all(len(op.parameters) == 0 for op in sampled.oplist))
def test_pauli_expect_op_vector(self): """pauli expect op vector test""" paulis_op = ListOp([X, Y, Z, I]) converted_meas = self.expect.convert(~StateFn(paulis_op)) plus_mean = converted_meas @ Plus sampled_plus = self.sampler.convert(plus_mean) np.testing.assert_array_almost_equal(sampled_plus.eval(), [1, 0, 0, 1], decimal=1) minus_mean = converted_meas @ Minus sampled_minus = self.sampler.convert(minus_mean) np.testing.assert_array_almost_equal(sampled_minus.eval(), [-1, 0, 0, 1], decimal=1) zero_mean = converted_meas @ Zero sampled_zero = self.sampler.convert(zero_mean) np.testing.assert_array_almost_equal(sampled_zero.eval(), [0, 0, 1, 1], decimal=1) sum_zero = (Plus + Minus) * (0.5**0.5) sum_zero_mean = converted_meas @ sum_zero sampled_zero_mean = self.sampler.convert(sum_zero_mean) # !!NOTE!!: Depolarizing channel (Sampling) means interference # does not happen between circuits in sum, so expectation does # not equal expectation for Zero!! np.testing.assert_array_almost_equal(sampled_zero_mean.eval(), [0, 0, 0, 1])
def _eval_aux_ops( self, parameters: np.ndarray, aux_operators: List[OperatorBase], expectation: ExpectationBase, threshold: float = 1e-12, ) -> np.ndarray: # Create new CircuitSampler to avoid breaking existing one's caches. sampler = CircuitSampler(self.quantum_instance) aux_op_meas = expectation.convert( StateFn(ListOp(aux_operators), is_measurement=True)) aux_op_expect = aux_op_meas.compose( CircuitStateFn(self.ansatz.bind_parameters(parameters))) values = np.real(sampler.convert(aux_op_expect).eval()) # Discard values below threshold aux_op_results = values * (np.abs(values) > threshold) # Deal with the aux_op behavior where there can be Nones or Zero qubit Paulis in the list _aux_op_nones = [op is None for op in aux_operators] aux_operator_eigenvalues = [ None if is_none else [result] for (is_none, result) in zip(_aux_op_nones, aux_op_results) ] # As this has mixed types, since it can included None, it needs to explicitly pass object # data type to avoid numpy 1.19 warning message about implicit conversion being deprecated aux_operator_eigenvalues = np.array([aux_operator_eigenvalues], dtype=object) return aux_operator_eigenvalues
def _get_observable_evaluator( ansatz: QuantumCircuit, observables: Union[OperatorBase, List[OperatorBase]], expectation: ExpectationBase, sampler: CircuitSampler, ) -> Callable[[np.ndarray], Union[float, List[float]]]: """Get a callable to evaluate a (list of) observable(s) for given circuit parameters.""" if isinstance(observables, list): observables = ListOp(observables) expectation_value = StateFn(observables, is_measurement=True) @ StateFn(ansatz) converted = expectation.convert(expectation_value) ansatz_parameters = ansatz.parameters def evaluate_observables(theta: np.ndarray) -> Union[float, List[float]]: """Evaluate the observables for the ansatz parameters ``theta``. Args: theta: The ansatz parameters. Returns: The observables evaluated at the ansatz parameters. """ value_dict = dict(zip(ansatz_parameters, theta)) sampled = sampler.convert(converted, params=value_dict) return sampled.eval() return evaluate_observables
def test_grad_combo_fn_chain_rule_nat_grad(self): """Test the chain rule for a custom gradient combo function.""" np.random.seed(2) def combo_fn(x): amplitudes = x[0].primitive.data pdf = np.multiply(amplitudes, np.conj(amplitudes)) return np.sum(np.log(pdf)) / (-len(amplitudes)) def grad_combo_fn(x): amplitudes = x[0].primitive.data pdf = np.multiply(amplitudes, np.conj(amplitudes)) grad = [] for prob in pdf: grad += [-1 / prob] return grad try: qc = RealAmplitudes(2, reps=1) grad_op = ListOp([StateFn(qc)], combo_fn=combo_fn, grad_combo_fn=grad_combo_fn) grad = NaturalGradient(grad_method='lin_comb', regularization='ridge' ).convert(grad_op, qc.ordered_parameters) value_dict = dict( zip(qc.ordered_parameters, np.random.rand(len(qc.ordered_parameters)))) correct_values = [[0.20777236], [-18.92560338], [-15.89005475], [-10.44002031]] np.testing.assert_array_almost_equal(grad.assign_parameters(value_dict).eval(), correct_values, decimal=3) except MissingOptionalLibraryError as ex: self.skipTest(str(ex))
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_grad_combo_fn_chain_rule(self, method): """Test the chain rule for a custom gradient combo function.""" np.random.seed(2) def combo_fn(x): amplitudes = x[0].primitive.data pdf = np.multiply(amplitudes, np.conj(amplitudes)) return np.sum(np.log(pdf)) / (-len(amplitudes)) def grad_combo_fn(x): amplitudes = x[0].primitive.data pdf = np.multiply(amplitudes, np.conj(amplitudes)) grad = [] for prob in pdf: grad += [-1 / prob] return grad qc = RealAmplitudes(2, reps=1) grad_op = ListOp([StateFn(qc.decompose())], combo_fn=combo_fn, grad_combo_fn=grad_combo_fn) grad = Gradient(grad_method=method).convert(grad_op) value_dict = dict( zip(qc.ordered_parameters, np.random.rand(len(qc.ordered_parameters)))) correct_values = [ [(-0.16666259133549044 + 0j)], [(-7.244949702732864 + 0j)], [(-2.979791752749964 + 0j)], [(-5.310186078432614 + 0j)], ] np.testing.assert_array_almost_equal( grad.assign_parameters(value_dict).eval(), correct_values)
def _prepare_list_op( quantum_state: Union[Statevector, QuantumCircuit, OperatorBase, ], observables: ListOrDict[OperatorBase], ) -> ListOp: """ Accepts a list or a dictionary of operators and converts them to a ``ListOp``. Args: quantum_state: An unparametrized quantum circuit representing a quantum state that expectation values are computed against. observables: A list or a dictionary of operators. Returns: A ``ListOp`` that includes all provided observables. """ if isinstance(observables, dict): observables = list(observables.values()) if not isinstance(quantum_state, StateFn): quantum_state = StateFn(quantum_state) return ListOp([ StateFn(obs, is_measurement=True).compose(quantum_state) for obs in observables ])
def test_list_pauli_sum_op(self): """Test PauliExpectation for List[PauliSumOp]""" test_op = ListOp([~StateFn(PauliSumOp.from_list([("XX", 1), ("ZI", 3), ("ZZ", 5)]))]) observable = self.expect.convert(test_op) self.assertIsInstance(observable, ListOp) self.assertIsInstance(observable[0][0][0].primitive, PauliSumOp) self.assertIsInstance(observable[0][1][0].primitive, PauliSumOp)
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_jax_chain_rule(self, method: str, autograd: bool): """Test the chain rule functionality using Jax d<H>/d<X> = 2<X> d<H>/d<Z> = - sin(<Z>) <Z> = Tr(|psi><psi|Z) = sin(a)sin(b) <X> = Tr(|psi><psi|X) = cos(a) d<H>/da = d<H>/d<X> d<X>/da + d<H>/d<Z> d<Z>/da = - 2 cos(a)sin(a) - sin(sin(a)sin(b)) * cos(a)sin(b) d<H>/db = d<H>/d<X> d<X>/db + d<H>/d<Z> d<Z>/db = - sin(sin(a)sin(b)) * sin(a)cos(b) """ a = Parameter("a") b = Parameter("b") params = [a, b] q = QuantumRegister(1) qc = QuantumCircuit(q) qc.h(q) qc.rz(params[0], q[0]) qc.rx(params[1], q[0]) def combo_fn(x): return jnp.power(x[0], 2) + jnp.cos(x[1]) def grad_combo_fn(x): return np.array([2 * x[0], -np.sin(x[1])]) op = ListOp( [ ~StateFn(X) @ CircuitStateFn(primitive=qc, coeff=1.0), ~StateFn(Z) @ CircuitStateFn(primitive=qc, coeff=1.0), ], combo_fn=combo_fn, grad_combo_fn=None if autograd else grad_combo_fn, ) state_grad = Gradient(grad_method=method).convert(operator=op, params=params) values_dict = [ { a: np.pi / 4, b: np.pi }, { params[0]: np.pi / 4, params[1]: np.pi / 4 }, { params[0]: np.pi / 2, params[1]: np.pi / 4 }, ] correct_values = [[-1.0, 0.0], [-1.2397, -0.2397], [0, -0.45936]] for i, value_dict in enumerate(values_dict): np.testing.assert_array_almost_equal( state_grad.assign_parameters(value_dict).eval(), correct_values[i], decimal=1)
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_state_hessian_custom_combo_fn(self, method): """Test the state Hessian with on an operator which includes a user-defined combo_fn. Tr(|psi><psi|Z) = sin(a)sin(b) Tr(|psi><psi|X) = cos(a) d^2<H>/da^2 = - 0.5 cos(a) + 1 sin(a)sin(b) d^2<H>/dbda = - 1 cos(a)cos(b) d^2<H>/dbda = - 1 cos(a)cos(b) d^2<H>/db^2 = + 1 sin(a)sin(b) """ ham = 0.5 * X - 1 * Z a = Parameter("a") b = Parameter("b") params = [(a, a), (a, b), (b, b)] q = QuantumRegister(1) qc = QuantumCircuit(q) qc.h(q) qc.rz(a, q[0]) qc.rx(b, q[0]) op = ListOp( [~StateFn(ham) @ CircuitStateFn(primitive=qc, coeff=1.0)], combo_fn=lambda x: x[0]**3 + 4 * x[0], ) state_hess = Hessian(hess_method=method).convert(operator=op, params=params) values_dict = [ { a: np.pi / 4, b: np.pi }, { a: np.pi / 4, b: np.pi / 4 }, { a: np.pi / 2, b: np.pi / 4 }, ] correct_values = [ [-1.28163104, 2.56326208, 1.06066017], [-0.04495626, -2.40716991, 1.8125], [2.82842712, -1.5, 1.76776695], ] for i, value_dict in enumerate(values_dict): np.testing.assert_array_almost_equal( state_hess.assign_parameters(value_dict).eval(), correct_values[i], decimal=1)
def test_multi_representation_ops(self): """Test observables with mixed representations""" mixed_ops = ListOp([X.to_matrix_op(), H, H + I, X]) converted_meas = self.expect.convert(~StateFn(mixed_ops)) plus_mean = converted_meas @ Plus sampled_plus = self.sampler.convert(plus_mean) np.testing.assert_array_almost_equal(sampled_plus.eval(), [1, 0.5**0.5, (1 + 0.5**0.5), 1], decimal=1)
def test_pauli_expect_op_vector(self): """ pauli expect op vector test """ paulis_op = ListOp([X, Y, Z, I]) converted_meas = self.expect.convert(~StateFn(paulis_op)) plus_mean = (converted_meas @ Plus) np.testing.assert_array_almost_equal(plus_mean.eval(), [1, 0, 0, 1], decimal=1) sampled_plus = self.sampler.convert(plus_mean) np.testing.assert_array_almost_equal(sampled_plus.eval(), [1, 0, 0, 1], decimal=1) minus_mean = (converted_meas @ Minus) np.testing.assert_array_almost_equal(minus_mean.eval(), [-1, 0, 0, 1], decimal=1) sampled_minus = self.sampler.convert(minus_mean) np.testing.assert_array_almost_equal(sampled_minus.eval(), [-1, 0, 0, 1], decimal=1) zero_mean = (converted_meas @ Zero) np.testing.assert_array_almost_equal(zero_mean.eval(), [0, 0, 1, 1], decimal=1) sampled_zero = self.sampler.convert(zero_mean) np.testing.assert_array_almost_equal(sampled_zero.eval(), [0, 0, 1, 1], decimal=1) sum_zero = (Plus + Minus) * (.5**.5) sum_zero_mean = (converted_meas @ sum_zero) np.testing.assert_array_almost_equal(sum_zero_mean.eval(), [0, 0, 1, 1], decimal=1) sampled_zero_mean = self.sampler.convert(sum_zero_mean) # !!NOTE!!: Depolarizing channel (Sampling) means interference # does not happen between circuits in sum, so expectation does # not equal expectation for Zero!! np.testing.assert_array_almost_equal(sampled_zero_mean.eval(), [0, 0, 0, 1], decimal=1) for i, op in enumerate(paulis_op.oplist): mat_op = op.to_matrix() np.testing.assert_array_almost_equal( zero_mean.eval()[i], Zero.adjoint().to_matrix() @ mat_op @ Zero.to_matrix(), decimal=1) np.testing.assert_array_almost_equal( plus_mean.eval()[i], Plus.adjoint().to_matrix() @ mat_op @ Plus.to_matrix(), decimal=1) np.testing.assert_array_almost_equal( minus_mean.eval()[i], Minus.adjoint().to_matrix() @ mat_op @ Minus.to_matrix(), decimal=1)
def test_pauli_expect_op_vector(self): """pauli expect op vector test""" paulis_op = ListOp([X, Y, Z, I]) converted_meas = self.expect.convert(~StateFn(paulis_op)) plus_mean = converted_meas @ Plus np.testing.assert_array_almost_equal(plus_mean.eval(), [1, 0, 0, 1], decimal=1) sampled_plus = self.sampler.convert(plus_mean) np.testing.assert_array_almost_equal(sampled_plus.eval(), [1, 0, 0, 1], decimal=1) minus_mean = converted_meas @ Minus np.testing.assert_array_almost_equal(minus_mean.eval(), [-1, 0, 0, 1], decimal=1) sampled_minus = self.sampler.convert(minus_mean) np.testing.assert_array_almost_equal(sampled_minus.eval(), [-1, 0, 0, 1], decimal=1) zero_mean = converted_meas @ Zero np.testing.assert_array_almost_equal(zero_mean.eval(), [0, 0, 1, 1], decimal=1) sampled_zero = self.sampler.convert(zero_mean) np.testing.assert_array_almost_equal(sampled_zero.eval(), [0, 0, 1, 1], decimal=1) sum_zero = (Plus + Minus) * (0.5**0.5) sum_zero_mean = converted_meas @ sum_zero np.testing.assert_array_almost_equal(sum_zero_mean.eval(), [0, 0, 1, 1], decimal=1) sampled_zero = self.sampler.convert(sum_zero) np.testing.assert_array_almost_equal( (converted_meas @ sampled_zero).eval(), [0, 0, 1, 1], decimal=1) for i, op in enumerate(paulis_op.oplist): mat_op = op.to_matrix() np.testing.assert_array_almost_equal( zero_mean.eval()[i], Zero.adjoint().to_matrix() @ mat_op @ Zero.to_matrix(), decimal=1, ) np.testing.assert_array_almost_equal( plus_mean.eval()[i], Plus.adjoint().to_matrix() @ mat_op @ Plus.to_matrix(), decimal=1, ) np.testing.assert_array_almost_equal( minus_mean.eval()[i], Minus.adjoint().to_matrix() @ mat_op @ Minus.to_matrix(), decimal=1, )
def test_pauli_expect_non_hermitian_pauliop(self): """pauli expect state vector with non hermitian operator test""" states_op = ListOp([One, Zero, Plus, Minus]) op = 1j * X converted_meas = self.expect.convert( StateFn(op, is_measurement=True) @ states_op) sampled = self.sampler.convert(converted_meas) np.testing.assert_array_almost_equal(sampled.eval(), [0, 0, 1j, -1j], decimal=1)
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_pauli_expect_state_vector(self): """pauli expect state vector test""" states_op = ListOp([One, Zero, Plus, Minus]) paulis_op = X converted_meas = self.expect.convert(~StateFn(paulis_op) @ states_op) sampled = self.sampler.convert(converted_meas) # Small test to see if execution results are accessible for composed_op in sampled: self.assertIn("counts", composed_op[0].execution_results) np.testing.assert_array_almost_equal(sampled.eval(), [0, 0, 1, -1], decimal=1)