Exemple #1
0
    def test_gradient_rzz(self, method):
        # pylint: disable=wrong-spelling-in-comment
        """Test the state gradient for ZZ rotation
        """
        ham = Z ^ X
        a = Parameter('a')

        q = QuantumRegister(2)
        qc = QuantumCircuit(q)
        qc.h(q[0])
        qc.rzz(a, q[0], q[1])

        op = ~StateFn(ham) @ CircuitStateFn(primitive=qc, coeff=1.)
        params = [a]
        state_grad = Gradient(grad_method=method).convert(operator=op,
                                                          params=params)
        values_dict = [{a: np.pi / 4}, {a: np.pi / 2}]
        correct_values = [[-0.707], [-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_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) @ 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 evaluate_operators(
        self, state: Union[str, dict, Result, list, np.ndarray, Statevector,
                           QuantumCircuit, Instruction, OperatorBase],
        operators: Union[WeightedPauliOperator, OperatorBase, list, dict]
    ) -> Union[float, List[float], Dict[str, List[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 ``WeightedPauliOperator``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.
        """
        # try to get a QuantumInstance from the solver
        quantum_instance = getattr(self._solver, 'quantum_instance', 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 = []
            for op in operators:
                results.append(self._eval_op(state, op, quantum_instance))
        elif isinstance(operators, dict):
            results = {}  # type: ignore
            for name, op in operators.items():
                results[name] = self._eval_op(state, op, quantum_instance)
        else:
            results = self._eval_op(state, operators, quantum_instance)

        return results
Exemple #4
0
    def construct_circuit(
        self, parameter: Union[List[float], List[Parameter], np.ndarray]
    ) -> OperatorBase:
        r"""
        Generate the ansatz circuit and expectation value measurement, and return their
        runnable composition.

        Args:
            parameter: Parameters for the ansatz circuit.

        Returns:
            The Operator equalling the measurement of the ansatz :class:`StateFn` by the
            Observable's expectation :class:`StateFn`.

        Raises:
            AquaError: If no operator has been provided.
        """
        if self.operator is None:
            raise AquaError("The operator was never provided.")

        # ensure operator and varform are compatible
        self._check_operator_varform()

        if isinstance(self.var_form, QuantumCircuit):
            param_dict = dict(zip(self._var_form_params, parameter))
            wave_function = self.var_form.assign_parameters(param_dict)
        else:
            wave_function = self.var_form.construct_circuit(parameter)

        # If ExpectationValue was never created, create one now.
        if not self.expectation:
            self._try_set_expectation_value_from_factory()

        observable_meas = self.expectation.convert(
            StateFn(self.operator, is_measurement=True))
        ansatz_circuit_op = CircuitStateFn(wave_function)
        return observable_meas.compose(ansatz_circuit_op).reduce()
    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

        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)
Exemple #6
0
    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)
Exemple #8
0
#        qc.cx(c[0], c[1])

#Acting the gates on circuit
for i in range (g):
    gates()

# Prepare the Ising Hamiltonian
#n = 3 #number of qubits
a = 1.0 
k = 2
t = range(1, n+1)

mdl = Model()# build model with docplex
x = [mdl.binary_var() for i in range(n)]
objective = a*(k - mdl.sum(t[i]*x[i] for i in range(n)))**2
mdl.minimize(objective)

qp = QuadraticProgram()# convert to Qiskit's quadratic program
qp.from_docplex(mdl)

qp2ising = QuadraticProgramToIsing()# convert to Ising Hamiltonian
H, offset = qp2ising.encode(qp)
H_matrix = np.real(H.to_matrix())    

psi = StateFn(qc)

expectation_value = (~psi @ H @ psi).eval()

print(psi)
print(expectation_value)
Exemple #9
0
    def _parameter_shift(
        self, operator: OperatorBase, params: Union[ParameterExpression,
                                                    ParameterVector,
                                                    List]) -> OperatorBase:
        r"""
        Args:
            operator: The operator containing circuits we are taking the derivative of.
            params: The parameters (ω) we are taking the derivative with respect to. If
                    a ParameterVector is provided, each parameter will be shifted.
        Returns:
            param_shifted_op: An operator object which evaluates to the respective gradients.

        Raises:
            ValueError: If the given parameters do not occur in the provided operator
            TypeError: If the operator has more than one circuit representing the quantum state
        """
        if isinstance(params, (ParameterVector, list)):
            param_grads = [
                self._parameter_shift(operator, param) for param in params
            ]
            absent_params = [
                params[i] for i, grad_ops in enumerate(param_grads)
                if grad_ops is None
            ]
            if len(absent_params) > 0:
                raise ValueError(
                    "The following parameters do not appear in the provided operator: ",
                    absent_params)
            return ListOp(absent_params)

        # By this point, it's only one parameter
        param = params

        if not isinstance(param, ParameterExpression):
            raise ValueError
        if isinstance(operator,
                      ListOp) and not isinstance(operator, ComposedOp):
            return_op = operator.traverse(
                partial(self._parameter_shift, params=param))

            # Remove any branch of the tree where the relevant parameter does not occur
            trimmed_oplist = [op for op in return_op.oplist if op is not None]
            # If all branches are None, remove the parent too
            if len(trimmed_oplist) == 0:
                return None
            # Rebuild the operator with the trimmed down oplist
            properties = {
                'coeff': return_op._coeff,
                'abelian': return_op._abelian
            }
            if return_op.__class__ == ListOp:
                properties['combo_fn'] = return_op.combo_fn
            return return_op.__class__(oplist=trimmed_oplist, **properties)

        else:
            circs = self.get_unique_circuits(operator)

            if len(circs) > 1:
                raise TypeError(
                    'Please define an operator with a single circuit representing '
                    'the quantum state.')
            if len(circs) == 0:
                return operator
            circ = circs[0]

            if self.analytic:
                # Unroll the circuit into a gate set for which the gradient may be computed
                # using pi/2 shifts.
                circ = ParamShift._unroll_to_supported_operations(circ)
                operator = ParamShift._replace_operator_circuit(operator, circ)

            if param not in circ._parameter_table:
                return ~Zero @ One

            shifted_ops = []
            summed_shifted_op = None
            for m, param_occurence in enumerate(circ._parameter_table[param]):
                param_index = param_occurence[1]
                pshift_op = deepcopy(operator)
                mshift_op = deepcopy(operator)

                # We need the circuit objects of the newly instantiated operators
                pshift_circ = self.get_unique_circuits(pshift_op)[0]
                mshift_circ = self.get_unique_circuits(mshift_op)[0]

                pshift_gate = pshift_circ._parameter_table[param][m][0]
                mshift_gate = mshift_circ._parameter_table[param][m][0]

                p_param = pshift_gate.params[param_index]
                m_param = mshift_gate.params[param_index]
                # For analytic gradients the circuit parameters are shifted once by +pi/2 and
                # once by -pi/2.
                if self.analytic:
                    shift_constant = 0.5
                    pshift_gate.params[param_index] = (p_param +
                                                       (np.pi /
                                                        (4 * shift_constant)))
                    mshift_gate.params[param_index] = (m_param -
                                                       (np.pi /
                                                        (4 * shift_constant)))
                # For finite difference gradients the circuit parameters are shifted once by
                # +epsilon and once by -epsilon.
                else:
                    shift_constant = 1. / (2 * self._epsilon)
                    pshift_gate.params[param_index] = (p_param + self._epsilon)
                    mshift_gate.params[param_index] = (m_param - self._epsilon)
                # The results of the shifted operators are now evaluated according the parameter
                # shift / finite difference formula.
                if isinstance(operator, ComposedOp):
                    shifted_op = shift_constant * (pshift_op - mshift_op)
                # If the operator represents a quantum state then we apply a special combo
                # function to evaluate probability gradients.
                elif isinstance(operator, StateFn):
                    shifted_op = ListOp([pshift_op, mshift_op],
                                        combo_fn=partial(
                                            self._prob_combo_fn,
                                            shift_constant=shift_constant))
                else:
                    raise TypeError(
                        'Probability gradients are not supported for the given '
                        'operator type')

                if isinstance(p_param, ParameterExpression) and not isinstance(
                        p_param, Parameter):
                    expr_grad = DerivativeBase.parameter_expression_grad(
                        p_param, param)
                    shifted_op *= expr_grad
                if not summed_shifted_op:
                    summed_shifted_op = shifted_op
                else:
                    summed_shifted_op += shifted_op

            shifted_ops.append(summed_shifted_op)

            if not SummedOp(shifted_ops).reduce():
                return ~StateFn(Zero) @ One
            else:
                return SummedOp(shifted_ops).reduce()
Exemple #10
0
    def _run(self) -> 'VQEResult':
        """Run the algorithm to compute the minimum eigenvalue.

        Returns:
            The result of the VQE algorithm as ``VQEResult``.

        Raises:
            AquaError: Wrong setting of operator and backend.
        """
        if self.operator is None:
            raise AquaError("The operator was never provided.")

        self._check_operator_varform()

        self._quantum_instance.circuit_summary = True

        self._eval_count = 0

        # Convert the gradient operator into a callable function that is compatible with the
        # optimization routine.
        if self._gradient:
            if isinstance(self._gradient, GradientBase):
                self._gradient = self._gradient.gradient_wrapper(
                    ~StateFn(self._operator) @ StateFn(self._var_form),
                    bind_params=self._var_form_params,
                    backend=self._quantum_instance)
        vqresult = self.find_minimum(initial_point=self.initial_point,
                                     var_form=self.var_form,
                                     cost_fn=self._energy_evaluation,
                                     gradient_fn=self._gradient,
                                     optimizer=self.optimizer)

        # TODO remove all former dictionary logic
        self._ret = {}
        self._ret['num_optimizer_evals'] = vqresult.optimizer_evals
        self._ret['min_val'] = vqresult.optimal_value
        self._ret['opt_params'] = vqresult.optimal_point
        self._ret['eval_time'] = vqresult.optimizer_time
        self._ret['opt_params_dict'] = vqresult.optimal_parameters

        if self._ret['num_optimizer_evals'] is not None and \
                self._eval_count >= self._ret['num_optimizer_evals']:
            self._eval_count = self._ret['num_optimizer_evals']
        self._eval_time = self._ret['eval_time']
        logger.info('Optimization complete in %s seconds.\nFound opt_params %s in %s evals',
                    self._eval_time, self._ret['opt_params'], self._eval_count)
        self._ret['eval_count'] = self._eval_count

        result = VQEResult()
        result.combine(vqresult)
        result.eigenvalue = vqresult.optimal_value + 0j
        result.eigenstate = self.get_optimal_vector()

        self._ret['energy'] = self.get_optimal_cost()
        self._ret['eigvals'] = np.asarray([self._ret['energy']])
        self._ret['eigvecs'] = np.asarray([result.eigenstate])

        if len(self.aux_operators) > 0:
            self._eval_aux_ops()
            # TODO remove when ._ret is deprecated
            result.aux_operator_eigenvalues = self._ret['aux_ops'][0]

        result.cost_function_evals = self._eval_count

        return result
    def _run(self):
        """
        Run the algorithm to compute up to the requested k number of eigenvalues.
        Returns:
            dict: Dictionary of results
        Raises:
            AquaError: if no operator has been provided
        """
        if self._operator is None:
            raise AquaError("Operator was never provided")

        k_orig = self._k
        if self._filter_criterion:
            # need to consider all elements if a filter is set
            self._k = 2**(self._operator.num_qubits)

        self._ret = {}
        self._solve()

        # compute energies before filtering, as this also evaluates the aux operators
        self._get_energies()

        # if a filter is set, loop over the given values and only keep
        if self._filter_criterion:

            eigvecs = []
            eigvals = []
            energies = []
            aux_ops = []
            cnt = 0
            for i in range(len(self._ret['eigvals'])):
                eigvec = self._ret['eigvecs'][i]
                eigval = self._ret['eigvals'][i]
                energy = self._ret['energies'][i]
                if 'aux_ops' in self._ret:
                    aux_op = self._ret['aux_ops'][i]
                else:
                    aux_op = None
                if self._filter_criterion(eigvec, eigval, aux_op):
                    cnt += 1
                    eigvecs += [eigvec]
                    eigvals += [eigval]
                    energies += [energy]
                    if 'aux_ops' in self._ret:
                        aux_ops += [aux_op]
                if cnt == k_orig:
                    break

            self._ret['eigvecs'] = np.array(eigvecs)
            self._ret['eigvals'] = np.array(eigvals)
            self._ret['energies'] = np.array(energies)

            self._k = k_orig

        # evaluate ground state after filtering (in case a filter is set)
        self._get_ground_state_energy()

        logger.debug('NumPyEigensolver _run result:\n%s',
                     pprint.pformat(self._ret, indent=4))
        result = EigensolverResult()
        if 'eigvals' in self._ret:
            result.eigenvalues = self._ret['eigvals']
        if 'eigvecs' in self._ret:
            result.eigenstates = ListOp([StateFn(vec) for vec in self._ret['eigvecs']])
        if 'aux_ops' in self._ret:
            result.aux_operator_eigenvalues = self._ret['aux_ops']

        logger.debug('EigensolverResult dict:\n%s',
                     pprint.pformat(result.data, indent=4))
        return result
    def test_parameterized_qobj(self):
        """ grouped pauli expectation test """
        two_qubit_h2 = (-1.052373245772859 * I ^ I) + \
                       (0.39793742484318045 * I ^ Z) + \
                       (-0.39793742484318045 * Z ^ I) + \
                       (-0.01128010425623538 * Z ^ Z) + \
                       (0.18093119978423156 * X ^ X)

        aer_sampler = CircuitSampler(self.sampler.quantum_instance,
                                     param_qobj=True,
                                     attach_results=True)

        var_form = RealAmplitudes()
        var_form.num_qubits = 2

        observable_meas = self.expect.convert(
            StateFn(two_qubit_h2, is_measurement=True))
        ansatz_circuit_op = CircuitStateFn(var_form)
        expect_op = observable_meas.compose(ansatz_circuit_op).reduce()

        def generate_parameters(num):
            param_bindings = {}
            for param in var_form.parameters:
                values = []
                for _ in range(num):
                    values.append(np.random.rand())
                param_bindings[param] = values
            return param_bindings

        def validate_sampler(ideal, sut, param_bindings):
            expect_sampled = ideal.convert(expect_op,
                                           params=param_bindings).eval()
            actual_sampled = sut.convert(expect_op,
                                         params=param_bindings).eval()
            self.assertAlmostEqual(actual_sampled, expect_sampled, delta=.1)

        def get_circuit_templates(sampler):
            return sampler._transpiled_circ_templates

        def validate_aer_binding_used(templates):
            self.assertIsNotNone(templates)

        def validate_aer_templates_reused(prev_templates, cur_templates):
            self.assertIs(prev_templates, cur_templates)

        validate_sampler(self.sampler, aer_sampler, generate_parameters(1))
        cur_templates = get_circuit_templates(aer_sampler)

        validate_aer_binding_used(cur_templates)

        prev_templates = cur_templates
        validate_sampler(self.sampler, aer_sampler, generate_parameters(2))
        cur_templates = get_circuit_templates(aer_sampler)

        validate_aer_templates_reused(prev_templates, cur_templates)

        prev_templates = cur_templates
        validate_sampler(self.sampler, aer_sampler,
                         generate_parameters(2))  # same num of params
        cur_templates = get_circuit_templates(aer_sampler)

        validate_aer_templates_reused(prev_templates, cur_templates)
Exemple #13
0
        qc.y(0)
        operations_i.append('qc_new.y(0)')
    elif param == 5:
        qc.z(0)
        operations_i.append('qc_new.z(0)')
print(A)

qc.x(2)
qc.z(1)
qc.y(3)
qc.s(0)
qc.cx(0, 1)
# qc.swap(1, 3)
qc.cx(2, 3)

cliff_sf_target = StateFn(qc)

print(qc)
# %% randomly select a single qubit gate and randomly change it to another

# calculate overlap integral


def overlap_modules_square(psi_2):
    psi_1 = cliff_sf_target
    # return (psi_1.adjoint().compose(psi_2).eval().real) * (psi_2.adjoint().compose(psi_1).eval().real)
    return np.real((~psi_1 @ psi_2).eval() * (~psi_2 @ psi_1).eval())


# radom apply GATE_FUNCTIONS
applied_gates = []
qp = QuadraticProgram()  # convert to Qiskit's quadratic program
qp.from_docplex(mdl)

qp2ising = QuadraticProgramToIsing()  # convert to Ising Hamiltonian
H, offset = qp2ising.encode(qp)
op = H.to_pauli_op()
help(H)
print(H)

# Prepare the state
qc = QuantumCircuit(3)
qc.h(0)
qc.cx(0, 1)
qc.cy(1, 2)
psi = StateFn(qc)  # wrap it into a statefunction
print(psi)

# Calculate the expectation value for Ising Hamiltonian
print('expectation_value:', psi.adjoint().compose(op).compose(psi).eval().real)

# %% another way of calculating expectation


# define your backend or quantum instance (where you can add settings)
backend = Aer.get_backend('qasm_simulator')
q_instance = QuantumInstance(backend, shots=1024)

# define the state to sample
measurable_expression = StateFn(op, is_measurement=True).compose(psi)