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_adjoint_nonunitary_circuit_raises(self): """Test adjoint on a non-unitary circuit raises a OpflowError instead of CircuitError.""" circuit = QuantumCircuit(1) circuit.reset(0) with self.assertRaises(OpflowError): _ = StateFn(circuit).adjoint()
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 test_state_gradient4(self, method): """Test the state gradient 4 Tr(|psi><psi|ZX) = -cos(a) daTr(|psi><psi|ZX) = sin(a) """ ham = X ^ Z a = Parameter('a') params = a q = QuantumRegister(2) qc = QuantumCircuit(q) qc.x(q[0]) qc.h(q[1]) qc.crz(a, q[0], q[1]) op = ~StateFn(ham) @ CircuitStateFn(primitive=qc, coeff=1.) state_grad = Gradient(grad_method=method).convert(operator=op, params=params) values_dict = [{a: np.pi / 4}, {a: 0}, {a: np.pi / 2}] correct_values = [1 / np.sqrt(2), 0, 1] 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_pauli_expectation_param_qobj(self): """ Test PauliExpectation with param_qobj """ q_instance = QuantumInstance(self.backend, seed_simulator=self.seed, seed_transpiler=self.seed, shots=10000) qubit_op = (0.1 * I ^ I) + (0.2 * I ^ Z) + (0.3 * Z ^ I) + ( 0.4 * Z ^ Z) + (0.5 * X ^ X) var_form = RealAmplitudes(qubit_op.num_qubits) ansatz_circuit_op = CircuitStateFn(var_form) observable = PauliExpectation().convert(~StateFn(qubit_op)) expect_op = observable.compose(ansatz_circuit_op).reduce() params1 = {} params2 = {} for param in var_form.parameters: params1[param] = [0] params2[param] = [0, 0] sampler1 = CircuitSampler(backend=q_instance, param_qobj=False) samples1 = sampler1.convert(expect_op, params=params1) val1 = np.real(samples1.eval())[0] samples2 = sampler1.convert(expect_op, params=params2) val2 = np.real(samples2.eval()) sampler2 = CircuitSampler(backend=q_instance, param_qobj=True) samples3 = sampler2.convert(expect_op, params=params1) val3 = np.real(samples3.eval()) samples4 = sampler2.convert(expect_op, params=params2) val4 = np.real(samples4.eval()) np.testing.assert_array_almost_equal([val1] * 2, val2, decimal=2) np.testing.assert_array_almost_equal(val1, val3, decimal=2) np.testing.assert_array_almost_equal([val1] * 2, val4, decimal=2)
def evaluate_operators( self, state: Union[str, dict, Result, list, np.ndarray, Statevector, QuantumCircuit, Instruction, OperatorBase, ], operators: Union[PauliSumOp, OperatorBase, list, dict], ) -> Union[Optional[float], List[Optional[float]], Dict[ str, List[Optional[float]]]]: """Evaluates additional operators at the given state. Args: state: any kind of input that can be used to specify a state. See also ``StateFn`` for more details. operators: either a single, list or dictionary of ``PauliSumOp``s or any kind of operator implementing the ``OperatorBase``. Returns: The expectation value of the given operator(s). The return type will be identical to the format of the provided operators. """ if isinstance(self._solver, MinimumEigensolverFactory): # try to get a QuantumInstance from the solver quantum_instance = getattr(self._solver.minimum_eigensolver, "quantum_instance", None) # and try to get an Expectation from the solver expectation = getattr(self._solver.minimum_eigensolver, "expectation", None) else: quantum_instance = getattr(self._solver, "quantum_instance", None) expectation = getattr(self._solver, "expectation", None) if not isinstance(state, StateFn): state = StateFn(state) # handle all possible formats of operators # i.e. if a user gives us a dict of operators, we return the results equivalently, etc. if isinstance(operators, list): results = [] # type: ignore for op in operators: if op is None: results.append(None) else: results.append( self._eval_op(state, op, quantum_instance, expectation)) elif isinstance(operators, dict): results = {} # type: ignore for name, op in operators.items(): if op is None: results[name] = None else: results[name] = self._eval_op(state, op, quantum_instance, expectation) else: if operators is None: results = None else: results = self._eval_op(state, operators, quantum_instance, expectation) return results
def test_operator_coefficient_gradient(self, method): """Test the operator coefficient gradient Tr( | psi > < psi | Z) = sin(a)sin(b) Tr( | psi > < psi | X) = cos(a) """ a = Parameter("a") b = Parameter("b") q = QuantumRegister(1) qc = QuantumCircuit(q) qc.h(q) qc.rz(a, q[0]) qc.rx(b, q[0]) coeff_0 = Parameter("c_0") coeff_1 = Parameter("c_1") ham = coeff_0 * X + coeff_1 * Z op = StateFn(ham, is_measurement=True) @ CircuitStateFn(primitive=qc, coeff=1.0) gradient_coeffs = [coeff_0, coeff_1] coeff_grad = Gradient(grad_method=method).convert(op, gradient_coeffs) values_dict = [ {coeff_0: 0.5, coeff_1: -1, a: np.pi / 4, b: np.pi}, {coeff_0: 0.5, coeff_1: -1, a: np.pi / 4, b: np.pi / 4}, ] correct_values = [[1 / np.sqrt(2), 0], [1 / np.sqrt(2), 1 / 2]] for i, value_dict in enumerate(values_dict): np.testing.assert_array_almost_equal( coeff_grad.assign_parameters(value_dict).eval(), correct_values[i], decimal=1 )
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 test_natural_gradient(self, method, regularization): """Test the natural gradient""" try: for params in (ParameterVector("a", 2), [Parameter("a"), Parameter("b")]): ham = 0.5 * X - 1 * Z q = QuantumRegister(1) qc = QuantumCircuit(q) qc.h(q) qc.rz(params[0], q[0]) qc.rx(params[1], q[0]) op = ~StateFn(ham) @ CircuitStateFn(primitive=qc, coeff=1.0) nat_grad = NaturalGradient( grad_method=method, regularization=regularization ).convert(operator=op) values_dict = [{params[0]: np.pi / 4, params[1]: np.pi / 2}] # reference values obtained by classically computing the natural gradients correct_values = [[-3.26, 1.63]] if regularization == "ridge" else [[-4.24, 0]] for i, value_dict in enumerate(values_dict): np.testing.assert_array_almost_equal( nat_grad.assign_parameters(value_dict).eval(), correct_values[i], decimal=1 ) except MissingOptionalLibraryError as ex: self.skipTest(str(ex))
def _eval_op(self, state, op, quantum_instance, expectation): # if the operator is empty we simply return 0 if op == 0: # Note, that for some reason the individual results need to be wrapped in lists. # See also: VQE._eval_aux_ops() return [0.0j] exp = ~StateFn(op) @ state # <state|op|state> if quantum_instance is not None: try: sampler = CircuitSampler(quantum_instance) if expectation is not None: exp = expectation.convert(exp) result = sampler.convert(exp).eval() except ValueError: # TODO make this cleaner. The reason for it being here is that some quantum # instances can lead to non-positive statevectors which the Qiskit circuit # Initializer is unable to handle. result = exp.eval() else: result = exp.eval() # Note, that for some reason the individual results need to be wrapped in lists. # See also: VQE._eval_aux_ops() return [result]
def test_state_gradient3(self, method): """Test the state gradient 3 Tr(|psi><psi|Z) = sin(a)sin(c(a)) = sin(a)sin(cos(a)+1) Tr(|psi><psi|X) = cos(a) d<H>/da = - 0.5 sin(a) - 1 cos(a)sin(cos(a)+1) + 1 sin^2(a)cos(cos(a)+1) """ ham = 0.5 * X - 1 * Z a = Parameter('a') # b = Parameter('b') params = a x = Symbol('x') expr = cos(x) + 1 c = ParameterExpression({a: x}, expr) q = QuantumRegister(1) qc = QuantumCircuit(q) qc.h(q) qc.rz(a, q[0]) qc.rx(c, q[0]) op = ~StateFn(ham) @ CircuitStateFn(primitive=qc, coeff=1.) state_grad = Gradient(grad_method=method).convert(operator=op, params=params) values_dict = [{a: np.pi / 4}, {a: 0}, {a: np.pi / 2}] correct_values = [-1.1220, -0.9093, 0.0403] 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_natural_gradient(self, method, regularization): """Test the natural gradient""" try: ham = 0.5 * X - 1 * Z 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]) op = ~StateFn(ham) @ CircuitStateFn(primitive=qc, coeff=1.) nat_grad = NaturalGradient(grad_method=method, regularization=regularization).convert( operator=op, params=params) values_dict = [{params[0]: np.pi / 4, params[1]: np.pi / 2}] correct_values = [[-2.36003979, 2.06503481]] \ if regularization == 'ridge' else [[-4.2, 0]] for i, value_dict in enumerate(values_dict): np.testing.assert_array_almost_equal( nat_grad.assign_parameters(value_dict).eval(), correct_values[i], decimal=0) except MissingOptionalLibraryError as ex: self.skipTest(str(ex))
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)], combo_fn=combo_fn, grad_combo_fn=grad_combo_fn) grad = Gradient(grad_method=method).convert(grad_op, qc.ordered_parameters) 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 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_natural_gradient4(self, grad_method, qfi_method, regularization): """Test the natural gradient 4""" # Avoid regularization = lasso intentionally because it does not converge try: ham = 0.5 * X - 1 * Z a = Parameter('a') params = a q = QuantumRegister(1) qc = QuantumCircuit(q) qc.h(q) qc.rz(a, q[0]) op = ~StateFn(ham) @ CircuitStateFn(primitive=qc, coeff=1.) nat_grad = NaturalGradient(grad_method=grad_method, qfi_method=qfi_method, regularization=regularization).convert( operator=op, params=params) values_dict = [{a: np.pi / 4}] correct_values = [[0.]] if regularization == 'ridge' else [[ -1.41421342 ]] for i, value_dict in enumerate(values_dict): np.testing.assert_array_almost_equal( nat_grad.assign_parameters(value_dict).eval(), correct_values[i], decimal=0) except MissingOptionalLibraryError as ex: self.skipTest(str(ex))
def test_gradient_p(self, method): """Test the state gradient for p |psi> = 1/sqrt(2)[[1, exp(ia)]] Tr(|psi><psi|Z) = 0 Tr(|psi><psi|X) = cos(a) d<H>/da = - 0.5 sin(a) """ ham = 0.5 * X - 1 * Z a = Parameter('a') params = a q = QuantumRegister(1) qc = QuantumCircuit(q) qc.h(q) qc.p(a, q[0]) op = ~StateFn(ham) @ CircuitStateFn(primitive=qc, coeff=1.) state_grad = Gradient(grad_method=method).convert(operator=op, params=params) values_dict = [{a: np.pi / 4}, {a: 0}, {a: np.pi / 2}] correct_values = [-0.5 / np.sqrt(2), 0, -0.5] 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_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) * (.5**.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, 2], decimal=1)
def test_state_gradient2(self, method): """Test the state gradient 2 Tr(|psi><psi|Z) = sin(a)sin(a) Tr(|psi><psi|X) = cos(a) d<H>/da = - 0.5 sin(a) - 2 cos(a)sin(a) """ ham = 0.5 * X - 1 * Z a = Parameter('a') # b = Parameter('b') params = [a] q = QuantumRegister(1) qc = QuantumCircuit(q) qc.h(q) qc.rz(a, q[0]) qc.rx(a, q[0]) op = ~StateFn(ham) @ CircuitStateFn(primitive=qc, coeff=1.) state_grad = Gradient(grad_method=method).convert(operator=op, params=params) values_dict = [{a: np.pi / 4}, {a: 0}, {a: np.pi / 2}] correct_values = [-1.353553, -0, -0.5] 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_circuit_sampler(self, method): """Test the gradient with circuit sampler Tr(|psi><psi|Z) = sin(a)sin(b) Tr(|psi><psi|X) = cos(a) d<H>/da = - 0.5 sin(a) - 1 cos(a)sin(b) d<H>/db = - 1 sin(a)cos(b) """ ham = 0.5 * X - 1 * Z 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]) op = ~StateFn(ham) @ CircuitStateFn(primitive=qc, coeff=1.0) shots = 8000 if method == "fin_diff": np.random.seed(8) state_grad = Gradient(grad_method=method, epsilon=shots**(-1 / 6.0)).convert(operator=op) else: state_grad = Gradient(grad_method=method).convert(operator=op) 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 = [ [-0.5 / np.sqrt(2), 1 / np.sqrt(2)], [-0.5 / np.sqrt(2) - 0.5, -1 / 2.0], [-0.5, -1 / np.sqrt(2)], ] backend = BasicAer.get_backend("qasm_simulator") q_instance = QuantumInstance(backend=backend, shots=shots) for i, value_dict in enumerate(values_dict): sampler = CircuitSampler(backend=q_instance).convert( state_grad, params={k: [v] for k, v in value_dict.items()}) np.testing.assert_array_almost_equal(sampler.eval()[0], correct_values[i], decimal=1)
def test_add_direct(self): """add direct test""" wf = StateFn({"101010": 0.5, "111111": 0.3}) + (Zero ^ 6) self.assertEqual(wf.primitive, { "101010": 0.5, "111111": 0.3, "000000": 1.0 }) wf = (4 * StateFn({ "101010": 0.5, "111111": 0.3 })) + ((3 + 0.1j) * (Zero ^ 6)) self.assertEqual(wf.primitive, { "000000": (3 + 0.1j), "101010": (2 + 0j), "111111": (1.2 + 0j) })
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_add_direct(self): """ add direct test """ wf = StateFn({'101010': .5, '111111': .3}) + (Zero ^ 6) self.assertEqual(wf.primitive, { '101010': 0.5, '111111': 0.3, '000000': 1.0 }) wf = (4 * StateFn({ '101010': .5, '111111': .3 })) + ((3 + .1j) * (Zero ^ 6)) self.assertEqual(wf.primitive, { '000000': (3 + 0.1j), '101010': (2 + 0j), '111111': (1.2 + 0j) })
def test_pauli_two_design(self, method): """Test SPSA on the Pauli two-design example.""" circuit = PauliTwoDesign(3, reps=1, seed=1) parameters = list(circuit.parameters) obs = Z ^ Z ^ I expr = ~StateFn(obs) @ StateFn(circuit) initial_point = np.array([ 0.82311034, 0.02611798, 0.21077064, 0.61842177, 0.09828447, 0.62013131 ]) def objective(x): return expr.bind_parameters(dict(zip(parameters, x))).eval().real settings = {"maxiter": 100, "blocking": True, "allowed_increase": 0} if method == "2spsa": settings["second_order"] = True settings["regularization"] = 0.01 expected_nfev = settings["maxiter"] * 5 + 1 elif method == "qnspsa": settings["fidelity"] = QNSPSA.get_fidelity(circuit) settings["regularization"] = 0.001 settings["learning_rate"] = 0.05 settings["perturbation"] = 0.05 expected_nfev = settings["maxiter"] * 7 + 1 else: expected_nfev = settings["maxiter"] * 3 + 1 if method == "qnspsa": spsa = QNSPSA(**settings) else: spsa = SPSA(**settings) with self.assertWarns(DeprecationWarning): result = spsa.optimize(circuit.num_parameters, objective, initial_point=initial_point) with self.subTest("check final accuracy"): self.assertLess(result[1], -0.95) # final loss with self.subTest("check number of function calls"): self.assertEqual(result[2], expected_nfev) # function evaluations
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_overlap_qfi_raises_on_unsupported_gate(self): """Test the overlap QFI raises an appropriate error on multi-param unbound gates.""" x = Parameter("x") circuit = QuantumCircuit(1) circuit.p(x, 0) with self.assertRaises(NotImplementedError): _ = QFI("overlap_diag").convert(StateFn(circuit), [x])
def test_overlap_qfi_raises_on_multiparam(self): """Test the overlap QFI raises an appropriate error on multi-param unbound gates.""" x = ParameterVector("x", 2) circuit = QuantumCircuit(1) circuit.u(x[0], x[1], 2, 0) with self.assertRaises(NotImplementedError): _ = QFI("overlap_diag").convert(StateFn(circuit), [x])
def construct_total_circuit_local(self, time_step): ## This function creates the circuit that will be used to evaluate overlap and its gradient, in a local fashion # First, create the Trotter step step_h = time_step * self.hamiltonian trotter = PauliTrotterEvolution(reps=1) U_dt = trotter.convert(step_h.exp_i()).to_circuit() l_circ = self.ansatz.assign_parameters({self.params_vec: self.left}) r_circ = self.ansatz.assign_parameters({self.params_vec: self.right}) ## Projector zero_prj = StateFn(projector_zero_local(self.hamiltonian.num_qubits), is_measurement=True) state_wfn = zero_prj @ StateFn(r_circ + U_dt + l_circ.inverse()) return state_wfn
def test_circuit_state_fn_from_dict_initialize(self): """state fn circuit from dict initialize test""" statedict = {"101": 0.5, "100": 0.1, "000": 0.2, "111": 0.5} sfc = CircuitStateFn.from_dict(statedict) self.assertIsInstance(sfc, CircuitStateFn) samples = sfc.sample() np.testing.assert_array_almost_equal( StateFn(statedict).to_matrix(), np.round(sfc.to_matrix(), decimals=1)) for k, v in samples.items(): self.assertIn(k, statedict) # It's ok if these are far apart because the dict is sampled. self.assertAlmostEqual(v, np.abs(statedict[k])**0.5, delta=0.5) # Follows same code path as above, but testing to be thorough sfc_vector = CircuitStateFn.from_vector(StateFn(statedict).to_matrix()) np.testing.assert_array_almost_equal( StateFn(statedict).to_matrix(), sfc_vector.to_matrix())
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_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_sampling(self): """state fn circuit from dict initialize test""" statedict = { "101": 0.5 + 1.0j, "100": 0.1 + 2.0j, "000": 0.2 + 0.0j, "111": 0.5 + 1.0j } sfc = CircuitStateFn.from_dict(statedict) circ_samples = sfc.sample() dict_samples = StateFn(statedict).sample() vec_samples = StateFn(statedict).to_matrix_op().sample() for k, v in circ_samples.items(): self.assertIn(k, dict_samples) self.assertIn(k, vec_samples) # It's ok if these are far apart because the dict is sampled. self.assertAlmostEqual(v, np.abs(dict_samples[k])**0.5, delta=0.5) self.assertAlmostEqual(v, np.abs(vec_samples[k])**0.5, delta=0.5)