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.0) 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.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=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 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.) 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_natural_gradients_invalid(self): """test that an exception is thrown when an invalid gradient method is used""" solver = VQEUCCFactory(quantum_instance=QuantumInstance( BasicAer.get_backend("statevector_simulator"))) grad = NaturalGradient(grad_method="fin_diff", qfi_method="lin_comb_full", regularization="ridge") calc = AdaptVQE(self.qubit_converter, solver, gradient=grad) with self.assertRaises(QiskitNatureError): _ = calc.solve(self.problem)
def test_gradient_wrapper2(self, backend_type, atol): """Test the gradient wrapper for gradients checking that statevector and qasm gives the same results dp0/da = cos(a)sin(b) / 2 dp1/da = - cos(a)sin(b) / 2 dp0/db = sin(a)cos(b) / 2 dp1/db = - sin(a)cos(b) / 2 """ method = "lin_comb" a = Parameter("a") b = Parameter("b") params = [a, b] qc = QuantumCircuit(2) qc.h(1) qc.h(0) qc.sdg(1) qc.cz(0, 1) qc.ry(params[0], 0) qc.rz(params[1], 0) qc.h(1) obs = (Z ^ X) - (Y ^ Y) op = StateFn(obs, is_measurement=True) @ CircuitStateFn(primitive=qc) shots = 8192 if backend_type == "qasm_simulator" else 1 values = [[0, np.pi / 2], [np.pi / 4, np.pi / 4], [np.pi / 3, np.pi / 9]] correct_values = [[-4.0, 0], [-2.0, -4.82842712], [-0.68404029, -7.01396121]] for i, value in enumerate(values): backend = BasicAer.get_backend(backend_type) q_instance = QuantumInstance(backend=backend, shots=shots, seed_simulator=2, seed_transpiler=2) grad = NaturalGradient(grad_method=method).gradient_wrapper( operator=op, bind_params=params, backend=q_instance) result = grad(value) self.assertTrue(np.allclose(result, correct_values[i], atol=atol))
def test_natural_gradient3(self, qfi_method, circuit_qfi): """Test the natural gradient 3""" nat_grad = NaturalGradient(qfi_method=qfi_method) self.assertIsInstance(nat_grad.qfi_method, circuit_qfi)
def test_natural_gradient2(self): """Test the natural gradient 2""" with self.assertRaises(TypeError): _ = NaturalGradient().convert(None, None)
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 = 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]] backend = BasicAer.get_backend("qasm_simulator") q_instance = QuantumInstance(backend=backend, shots=5000) sampler = CircuitSampler(backend=q_instance).convert( grad, params={k: [v] for k, v in value_dict.items()} ) print('Sampler ', sampler.eval()[0]) print('Correct Values ', correct_values)