Exemplo n.º 1
0
        def _build_one_sector(available_hopping_ops, untapered_op,
                              z2_symmetries):

            to_be_computed_list = []
            for idx, _ in enumerate(mus):
                m_u = mus[idx]
                n_u = nus[idx]
                left_op = available_hopping_ops.get('E_{}'.format(m_u))
                right_op_1 = available_hopping_ops.get('E_{}'.format(n_u))
                right_op_2 = available_hopping_ops.get('Edag_{}'.format(n_u))
                to_be_computed_list.append(
                    (m_u, n_u, left_op, right_op_1, right_op_2))

            if logger.isEnabledFor(logging.INFO):
                logger.info("Building all commutators:")
                TextProgressBar(sys.stderr)
            results = parallel_map(
                self._build_commutator_routine,
                to_be_computed_list,
                task_args=(untapered_op, z2_symmetries),
                num_processes=algorithm_globals.num_processes)
            for result in results:
                m_u, n_u, q_mat_op, w_mat_op, m_mat_op, v_mat_op = result

                if q_mat_op is not None:
                    all_matrix_operators['q_{}_{}'.format(m_u, n_u)] = q_mat_op
                if w_mat_op is not None:
                    all_matrix_operators['w_{}_{}'.format(m_u, n_u)] = w_mat_op
                if m_mat_op is not None:
                    all_matrix_operators['m_{}_{}'.format(m_u, n_u)] = m_mat_op
                if v_mat_op is not None:
                    all_matrix_operators['v_{}_{}'.format(m_u, n_u)] = v_mat_op
Exemplo n.º 2
0
    def construct_circuit(
            self,
            parameters: Union[np.ndarray, List[Parameter], ParameterVector],
            q: Optional[QuantumRegister] = None) -> QuantumCircuit:
        """Construct the variational form, given its parameters.

        Args:
            parameters: circuit parameters
            q: Quantum Register for the circuit.

        Returns:
            Quantum Circuit a quantum circuit with given `parameters`

        Raises:
            ValueError: the number of parameters is incorrect.
            ValueError: if num_qubits has not been set and is still None
        """

        if len(parameters) != self._num_parameters:
            raise ValueError('The number of parameters has to be {}'.format(
                self._num_parameters))

        if self._num_qubits is None:
            raise ValueError(
                'The number of qubits is None and must be set before the circuit '
                'can be created.')

        if q is None:
            q = QuantumRegister(self._num_qubits, name='q')

        if isinstance(self._initial_state, QuantumCircuit):
            circuit = QuantumCircuit(q)
            circuit.append(self._initial_state.to_gate(),
                           range(self._initial_state.num_qubits))
        elif self._initial_state is not None:
            circuit = self._initial_state.construct_circuit('circuit', q)
        else:
            circuit = QuantumCircuit(q)

        if logger.isEnabledFor(
                logging.DEBUG) and self._logging_construct_circuit:
            logger.debug("Evolving hopping operators:")
            TextProgressBar(sys.stderr)
            self._logging_construct_circuit = False

        num_excitations = len(self._hopping_ops)

        results = parallel_map(
            UVCC._construct_circuit_for_one_excited_operator,
            [(self._hopping_ops[index % num_excitations], parameters[index])
             for index in range(self._reps * num_excitations)],
            task_args=(q, self._num_time_slices),
            num_processes=aqua_globals.num_processes)
        for qc in results:
            if self._shallow_circuit_concat:
                circuit.data += qc.data
            else:
                circuit += qc

        return circuit
Exemplo n.º 3
0
        def _build_one_sector(available_hopping_ops):

            to_be_computed_list = []
            for idx, _ in enumerate(mus):
                m_u = mus[idx]
                n_u = nus[idx]
                left_op = available_hopping_ops.get(
                    '_'.join([str(x) for x in excitations_list[m_u]]), None)
                right_op_1 = available_hopping_ops.get(
                    '_'.join([str(x) for x in excitations_list[n_u]]), None)
                right_op_2 = available_hopping_ops.get(
                    '_'.join([str(x) for x in reversed(excitations_list[n_u])]), None)
                to_be_computed_list.append((m_u, n_u, left_op, right_op_1, right_op_2))

            if logger.isEnabledFor(logging.INFO):
                logger.info("Building all commutators:")
                TextProgressBar(sys.stderr)
            results = parallel_map(QEquationOfMotion._build_commutator_rountine,
                                   to_be_computed_list,
                                   task_args=(self._untapered_op, self._z2_symmetries))
            for result in results:
                m_u, n_u, q_mat_op, w_mat_op, m_mat_op, v_mat_op = result
                q_commutators[m_u][n_u] = op_converter.to_tpb_grouped_weighted_pauli_operator(
                    q_mat_op, TPBGroupedWeightedPauliOperator.sorted_grouping) \
                    if q_mat_op is not None else q_commutators[m_u][n_u]
                w_commutators[m_u][n_u] = op_converter.to_tpb_grouped_weighted_pauli_operator(
                    w_mat_op, TPBGroupedWeightedPauliOperator.sorted_grouping) \
                    if w_mat_op is not None else w_commutators[m_u][n_u]
                m_commutators[m_u][n_u] = op_converter.to_tpb_grouped_weighted_pauli_operator(
                    m_mat_op, TPBGroupedWeightedPauliOperator.sorted_grouping) \
                    if m_mat_op is not None else m_commutators[m_u][n_u]
                v_commutators[m_u][n_u] = op_converter.to_tpb_grouped_weighted_pauli_operator(
                    v_mat_op, TPBGroupedWeightedPauliOperator.sorted_grouping) \
                    if v_mat_op is not None else v_commutators[m_u][n_u]
Exemplo n.º 4
0
def to_weighted_pauli_operator(operator):
    """
    Converting a given operator to `WeightedPauliOperator`

    Args:
        operator (WeightedPauliOperator | TPBGroupedWeightedPauliOperator | MatrixOperator | Operator):
            one of supported operator type
    Returns:
        WeightedPauliOperator: the converted weighted pauli operator
    """
    if operator.__class__ == WeightedPauliOperator:
        return operator
    elif operator.__class__ == TPBGroupedWeightedPauliOperator:
        # destroy the grouping but keep z2 symmetries info
        return WeightedPauliOperator(paulis=operator.paulis,
                                     z2_symmetries=operator.z2_symmetries,
                                     name=operator.name)
    elif operator.__class__ == MatrixOperator:
        if operator.is_empty():
            return WeightedPauliOperator(paulis=[])
        logger.warning(
            "Converting time from a MatrixOperator to a Pauli-type Operator grows exponentially. "
            "If you are converting a system with large number of qubits, it will take time. "
            "You can turn on DEBUG logging to check the progress.")
        num_qubits = operator.num_qubits
        coeff = 2**(-num_qubits)

        paulis = []
        possible_basis = 'IXYZ'
        if operator.dia_matrix is not None:
            possible_basis = 'IZ'

        if logger.isEnabledFor(logging.DEBUG):
            logger.debug(
                "Converting a MatrixOperator to a Pauli-type Operator:")
            TextProgressBar(sys.stderr)
        results = parallel_map(_conversion, [
            basis
            for basis in itertools.product(possible_basis, repeat=num_qubits)
        ],
                               task_kwargs={"matrix": operator._matrix},
                               num_processes=aqua_globals.num_processes)
        for trace_value, pauli in results:
            weight = trace_value * coeff
            if weight != 0.0 and np.abs(weight) > operator.atol:
                paulis.append([weight, pauli])

        return WeightedPauliOperator(paulis,
                                     z2_symmetries=operator.z2_symmetries,
                                     name=operator.name)
    elif operator.__class__ == Operator:
        warnings.warn(
            "The `Operator` class is deprecated. Please use `WeightedPauliOperator` or "
            "`TPBGroupedWeightedPauliOperator` or `MatrixOperator` instead",
            DeprecationWarning)
        return operator.to_weighted_pauli_operator()
    else:
        raise AquaError(
            "Unsupported type to convert to WeightedPauliOperator: {}".format(
                operator.__class__))
Exemplo n.º 5
0
    def _build_hopping_operators(self):
        if logger.isEnabledFor(logging.DEBUG):
            TextProgressBar(sys.stderr)

        results = parallel_map(
            UCCSD._build_hopping_operator,
            self._single_excitations + self._double_excitations,
            task_args=(self._num_orbitals, self._num_particles,
                       self._qubit_mapping, self._two_qubit_reduction,
                       self._z2_symmetries, self._skip_commute_test),
            num_processes=aqua_globals.num_processes)
        hopping_ops = []
        s_e_list = []
        d_e_list = []
        for op, index in results:
            if op is not None and not op.is_empty():
                hopping_ops.append(op)
                if len(index) == 2:  # for double excitation
                    s_e_list.append(index)
                else:  # for double excitation
                    d_e_list.append(index)

        self._single_excitations = s_e_list
        self._double_excitations = d_e_list

        num_parameters = len(hopping_ops) * self._depth
        return hopping_ops, num_parameters
Exemplo n.º 6
0
    def evaluate_with_result(self, result, statevector_mode, use_simulator_operator_mode=False,
                             circuit_name_prefix=''):
        """
        This method can be only used with the circuits generated by the
        `construct_evaluation_circuit` method with the same `circuit_name_prefix`
        since the circuit names are tied to some meanings.

        Calculate the evaluated value with the measurement results.

        Args:
            result (qiskit.Result): the result from the backend.
            statevector_mode (bool): indicate which type of simulator are used.
            use_simulator_operator_mode (bool): if aer_provider is used, we can do faster
                           evaluation for pauli mode on statevector simulation
            circuit_name_prefix (str): a prefix of circuit name

        Returns:
            float: the mean value
            float: the standard deviation

        Raises:
            AquaError: if Operator is empty
        """
        if self.is_empty():
            raise AquaError("Operator is empty, check the operator.")

        avg, std_dev, variance = 0.0, 0.0, 0.0
        if statevector_mode:
            if use_simulator_operator_mode:
                temp = \
                    result.data(
                        circuit_name_prefix + 'aer_mode')[
                            'snapshots']['expectation_value']['test'][0]['value']
                avg = temp[0] + 1j * temp[1]
            else:
                quantum_state = np.asarray(result.get_statevector(circuit_name_prefix + 'psi'))
                for weight, pauli in self._paulis:
                    # all I
                    if np.all(np.logical_not(pauli.z)) and np.all(np.logical_not(pauli.x)):
                        avg += weight
                    else:
                        quantum_state_i = \
                            result.get_statevector(circuit_name_prefix + pauli.to_label())
                        avg += (weight * (np.vdot(quantum_state, quantum_state_i)))
        else:
            if logger.isEnabledFor(logging.DEBUG):
                logger.debug("Computing the expectation from measurement results:")
                TextProgressBar(sys.stderr)
            # pick the first result to get the total number of shots
            num_shots = sum(list(result.get_counts(0).values()))
            results = parallel_map(WeightedPauliOperator._routine_compute_mean_and_var,
                                   [([self._paulis[idx] for idx in indices],
                                     result.get_counts(circuit_name_prefix + basis.to_label()))
                                    for basis, indices in self._basis],
                                   num_processes=aqua_globals.num_processes)
            for res in results:
                avg += res[0]
                variance += res[1]
            std_dev = np.sqrt(variance / num_shots)
        return avg, std_dev
Exemplo n.º 7
0
def to_weighted_pauli_operator(
        operator: Union[WeightedPauliOperator, TPBGroupedWeightedPauliOperator, MatrixOperator]) \
        -> WeightedPauliOperator:
    """
    Converting a given operator to `WeightedPauliOperator`

    Args:
        operator: one of supported operator type
    Returns:
        The converted weighted pauli operator
    Raises:
        AquaError: Unsupported type to convert

    Warnings:
        Converting time from a MatrixOperator to a Pauli-type Operator grows exponentially.
        If you are converting a system with large number of qubits, it will take time.
        You can turn on DEBUG logging to check the progress.
    """
    if operator.__class__ == WeightedPauliOperator:
        return cast(WeightedPauliOperator, operator)
    elif operator.__class__ == TPBGroupedWeightedPauliOperator:
        # destroy the grouping but keep z2 symmetries info
        op_tpb = cast(TPBGroupedWeightedPauliOperator, operator)
        return WeightedPauliOperator(paulis=op_tpb.paulis, z2_symmetries=op_tpb.z2_symmetries,
                                     name=op_tpb.name)
    elif operator.__class__ == MatrixOperator:
        op_m = cast(MatrixOperator, operator)
        if op_m.is_empty():
            return WeightedPauliOperator(paulis=[])
        if op_m.num_qubits > 10:
            logger.warning("Converting time from a MatrixOperator to a Pauli-type Operator grows "
                           "exponentially. If you are converting a system with large number of "
                           "qubits, it will take time. And now you are converting a %s-qubit "
                           "Hamiltonian. You can turn on DEBUG logging to check the progress."
                           "", op_m.num_qubits)
        num_qubits = op_m.num_qubits
        coeff = 2 ** (-num_qubits)

        paulis = []
        possible_basis = 'IXYZ'
        if op_m.dia_matrix is not None:
            possible_basis = 'IZ'

        if logger.isEnabledFor(logging.DEBUG):
            logger.debug("Converting a MatrixOperator to a Pauli-type Operator:")
            TextProgressBar(sys.stderr)
        results = parallel_map(_conversion,
                               list(itertools.product(possible_basis, repeat=num_qubits)),
                               task_kwargs={"matrix": op_m._matrix},
                               num_processes=aqua_globals.num_processes)
        for trace_value, pauli in results:
            weight = trace_value * coeff
            if weight != 0.0 and np.abs(weight) > op_m.atol:
                paulis.append([weight, pauli])

        return WeightedPauliOperator(paulis, z2_symmetries=operator.z2_symmetries,
                                     name=operator.name)
    else:
        raise AquaError("Unsupported type to convert to WeightedPauliOperator: "
                        "{}".format(operator.__class__))
Exemplo n.º 8
0
    def _build_hopping_operators(self):
        if logger.isEnabledFor(logging.DEBUG):
            TextProgressBar(sys.stderr)

        results = parallel_map(UVCC._build_hopping_operator, self._excitations,
                               task_args=(self._basis, 'direct'),
                               num_processes=algorithm_globals.num_processes)
        hopping_ops = [qubit_op for qubit_op in results if qubit_op is not None]
        num_parameters = len(hopping_ops) * self._reps

        return hopping_ops, num_parameters
Exemplo n.º 9
0
 def mapping_new(self, map_type, threshold=0.00000001):
     """Map fermionic operator to qubit operator.        Using multiprocess to speedup the mapping, the improvement can be
     observed when h2 is a non-sparse matrix.        Args:
         map_type (str): case-insensitive mapping type.
                         "jordan_wigner", "parity", "bravyi_kitaev", "bksf"
         threshold (float): threshold for Pauli simplification        Returns:
         WeightedPauliOperator: create an Operator object in Paulis form.        Raises:
         QiskitChemistryError: if the `map_type` can not be recognized.
     """        # ###################################################################
     # ###########   DEFINING MAPPED FERMIONIC OPERATORS    ##############
     # ###################################################################        self._map_type = map_type
     n = self._modes  # number of fermionic modes / qubits
     map_type = map_type.lower()
     if map_type == 'jordan_wigner':
         a_list = self._jordan_wigner_mode(n)
     elif map_type == 'parity':
         a_list = self._parity_mode(n)
     elif map_type == 'bravyi_kitaev':
         a_list = self._bravyi_kitaev_mode(n)
     elif map_type == 'bksf':
         return bksf_mapping(self)
     else:
         raise QiskitChemistryError('Please specify the supported modes: '
                                    'jordan_wigner, parity, bravyi_kitaev, bksf')        # ###################################################################
     # ###########    BUILDING THE MAPPED HAMILTONIAN     ################
     # ###################################################################        pauli_list = WeightedPauliOperator(paulis=[])
     if logger.isEnabledFor(logging.DEBUG):
         logger.debug("Mapping one-body terms to Qubit Hamiltonian:")
         TextProgressBar(output_handler=sys.stderr)
     results = parallel_map(FermionicOperator._n_body_mapping,
                            [(self._h1[i, j], a_list[i], a_list[j])
                             for i, j in itertools.product(range(n), repeat=2)
                             if self._h1[i, j] != 0],
                            task_args=(threshold,), num_processes=aqua_globals.num_processes)
     for result in results:
         pauli_list += result
     pauli_list.chop(threshold=threshold)        if logger.isEnabledFor(logging.DEBUG):
         logger.debug("Mapping two-body terms to Qubit Hamiltonian:")
         TextProgressBar(output_handler=sys.stderr)
Exemplo n.º 10
0
    def _build_hopping_operators(self):
        if logger.isEnabledFor(logging.DEBUG):
            TextProgressBar(sys.stderr)

        results = parallel_map(UCCSD._build_hopping_operator,
                               self._single_excitations + self._double_excitations,
                               task_args=(self._num_orbitals,
                                          self._num_particles, self._qubit_mapping,
                                          self._two_qubit_reduction, self._z2_symmetries),
                               num_processes=aqua_globals.num_processes)
        hopping_ops = [qubit_op for qubit_op in results if qubit_op is not None]
        num_parameters = len(hopping_ops) * self._depth
        return hopping_ops, num_parameters
Exemplo n.º 11
0
    def transpile(self):
        input_files = self.get_unrun_files(transpile_only=True)
        print('\n ============= TRANSPILATION ONLY ================')
        print('\n RESUMING \n')
        print(len(input_files), ' circuits left:')
        print(input_files)
        circ_list = self.create_circ_list(input_files)
        print('Circuits generated. Transpiling...')
        TextProgressBar()
        circ_list = compiler.transpile(circ_list,
                                       backend=self.backend,
                                       optimization_level=self.optim)

        for circ in circ_list:
            self.save_qasm(circ)
Exemplo n.º 12
0
    def construct_circuit(self, parameters, q=None):
        """
        Construct the variational form, given its parameters.

        Args:
            parameters (numpy.ndarray): circuit parameters
            q (QuantumRegister): Quantum Register for the circuit.

        Returns:
            QuantumCircuit: a quantum circuit with given `parameters`

        Raises:
            ValueError: the number of parameters is incorrect.
        """
        from .uccsd import UCCSD
        if len(parameters) != self._num_parameters:
            raise ValueError('The number of parameters has to be {}'.format(
                self._num_parameters))

        if q is None:
            q = QuantumRegister(self._num_qubits, name='q')
        if self._initial_state is not None:
            circuit = self._initial_state.construct_circuit('circuit', q)
        else:
            circuit = QuantumCircuit(q)

        if logger.isEnabledFor(
                logging.DEBUG) and self._logging_construct_circuit:
            logger.debug("Evolving hopping operators:")
            TextProgressBar(sys.stderr)
            self._logging_construct_circuit = False

        num_excitations = len(self._hopping_ops)
        results = parallel_map(
            UCCSD._construct_circuit_for_one_excited_operator,
            [(self._hopping_ops[index % num_excitations], parameters[index])
             for index in range(self._depth * num_excitations)],
            task_args=(q, self._num_time_slices),
            num_processes=aqua_globals.num_processes)
        for qc in results:
            if self._shallow_circuit_concat:
                circuit.data += qc.data
            else:
                circuit += qc

        return circuit
Exemplo n.º 13
0
    def _build_hopping_operators(self):
        from .uccsd import UCCSD
        hopping_ops = []

        if logger.isEnabledFor(logging.DEBUG):
            TextProgressBar(sys.stderr)

        results = parallel_map(
            UCCSD._build_hopping_operator,
            self._single_excitations + self._double_excitations,
            task_args=(self._num_orbitals, self._num_particles,
                       self._qubit_mapping, self._two_qubit_reduction,
                       self._qubit_tapering, self._symmetries, self._cliffords,
                       self._sq_list, self._tapering_values))
        hopping_ops = [
            qubit_op for qubit_op in results if qubit_op is not None
        ]
        num_parameters = len(hopping_ops) * self._depth
        return hopping_ops, num_parameters
Exemplo n.º 14
0
    def get_depth_and_size(self, dir, transpile=True, backend_name=None):
        # def _get_size_and_depth(self, row):
        #     name = row.name
        #     circ = QuantumCircuit.from_qasm_file(os.path.join(self.res_dir, name))
        #     row['depth'] = circ.depth()
        #     row['size'] = circ.size()
        # self.df.parallel_apply(_get_size_and_depth, axis=1)

        # def _get_size_and_depth(slice):
        #     for row in slice.iterrows():
        #         name = row.name
        #         circ = QuantumCircuit.from_qasm(os.path.join(self.res_dir, name))
        #         row['depth'] = circ.depth()
        #         row['size'] = circ.size()
        # self.df = parallelize_dataframe(self.df, _get_size_and_depth)
        if backend_name:
            IBMQ.load_accounts()
            backend = IBMQ.backends(
                filters=lambda x: x.name() == backend_name)[0]
        file_list = get_file_list(dir, '.qasm')
        file_list_abs = [os.path.join(dir, file) for file in file_list]
        pool = Pool()
        print('==Creating circuit list==')
        # circ_list = pool.map(QuantumCircuit.from_qasm_file, file_list_abs)
        circ_list = Parallel(n_jobs=cpu_count())(
            delayed(QuantumCircuit.from_qasm_file)(file)
            for file in file_list_abs)
        # pool.close()
        # pool.join()
        if transpile:
            print('==Transpiling!==')
            TextProgressBar()
            circ_list = compiler.transpile(circ_list, backend)
        file_list_pkl = [
            os.path.splitext(file)[0] + '.pkl' for file in file_list
        ]

        for i in range(len(file_list_pkl)):
            self.df.loc[file_list_pkl[i], 'depth'] = circ_list[i].depth()
            self.df.loc[file_list_pkl[i], 'size'] = circ_list[i].size()

        return
Exemplo n.º 15
0
    def get_kernel_matrix(quantum_instance,
                          feature_map,
                          x1_vec,
                          x2_vec=None,
                          enforce_psd=True):
        """
        Construct kernel matrix, if x2_vec is None, self-innerproduct is conducted.

        Notes:
            When using `statevector_simulator`,
            we only build the circuits for Psi(x1)|0> rather than
            Psi(x2)^dagger Psi(x1)|0>, and then we perform the inner product classically.
            That is, for `statevector_simulator`,
            the total number of circuits will be O(N) rather than
            O(N^2) for `qasm_simulator`.

        Args:
            quantum_instance (QuantumInstance): quantum backend with all settings
            feature_map (FeatureMap): a feature map that maps data to feature space
            x1_vec (numpy.ndarray): data points, 2-D array, N1xD, where N1 is the number of data,
                                    D is the feature dimension
            x2_vec (numpy.ndarray): data points, 2-D array, N2xD, where N2 is the number of data,
                                    D is the feature dimension
            enforce_psd (bool): enforces that the kernel matrix is positive semi-definite by setting
                                negative eigenvalues to zero. This is only applied in the symmetric
                                case, i.e., if `x2_vec == None`.
        Returns:
            numpy.ndarray: 2-D matrix, N1xN2
        """

        if isinstance(feature_map, QuantumCircuit):
            use_parameterized_circuits = True
        else:
            use_parameterized_circuits = feature_map.support_parameterized_circuit

        if x2_vec is None:
            is_symmetric = True
            x2_vec = x1_vec
        else:
            is_symmetric = False

        is_statevector_sim = quantum_instance.is_statevector

        measurement = not is_statevector_sim
        measurement_basis = '0' * feature_map.num_qubits
        mat = np.ones((x1_vec.shape[0], x2_vec.shape[0]))

        # get all indices
        if is_symmetric:
            mus, nus = np.triu_indices(x1_vec.shape[0],
                                       k=1)  # remove diagonal term
        else:
            mus, nus = np.indices((x1_vec.shape[0], x2_vec.shape[0]))
            mus = np.asarray(mus.flat)
            nus = np.asarray(nus.flat)

        if is_statevector_sim:
            if is_symmetric:
                to_be_computed_data = x1_vec
            else:
                to_be_computed_data = np.concatenate((x1_vec, x2_vec))

            if use_parameterized_circuits:
                # build parameterized circuits, it could be slower for building circuit
                # but overall it should be faster since it only transpile one circuit
                feature_map_params = ParameterVector(
                    'x', feature_map.feature_dimension)
                parameterized_circuit = QSVM._construct_circuit(
                    (feature_map_params, feature_map_params),
                    feature_map,
                    measurement,
                    is_statevector_sim=is_statevector_sim)
                parameterized_circuit = quantum_instance.transpile(
                    parameterized_circuit)[0]
                circuits = [
                    parameterized_circuit.assign_parameters(
                        {feature_map_params: x}) for x in to_be_computed_data
                ]
            else:
                #  the second x is redundant
                to_be_computed_data_pair = [(x, x)
                                            for x in to_be_computed_data]
                if logger.isEnabledFor(logging.DEBUG):
                    logger.debug("Building circuits:")
                    TextProgressBar(sys.stderr)
                circuits = parallel_map(
                    QSVM._construct_circuit,
                    to_be_computed_data_pair,
                    task_args=(feature_map, measurement, is_statevector_sim),
                    num_processes=aqua_globals.num_processes)

            results = quantum_instance.execute(
                circuits, had_transpiled=use_parameterized_circuits)

            if logger.isEnabledFor(logging.DEBUG):
                logger.debug("Calculating overlap:")
                TextProgressBar(sys.stderr)

            offset = 0 if is_symmetric else len(x1_vec)
            matrix_elements = parallel_map(
                QSVM._compute_overlap,
                list(zip(mus, nus + offset)),
                task_args=(results, is_statevector_sim, measurement_basis),
                num_processes=aqua_globals.num_processes)

            for i, j, value in zip(mus, nus, matrix_elements):
                mat[i, j] = value
                if is_symmetric:
                    mat[j, i] = mat[i, j]
        else:
            for idx in range(0, len(mus), QSVM.BATCH_SIZE):
                to_be_computed_data_pair = []
                to_be_computed_index = []
                for sub_idx in range(idx, min(idx + QSVM.BATCH_SIZE,
                                              len(mus))):
                    i = mus[sub_idx]
                    j = nus[sub_idx]
                    x1 = x1_vec[i]
                    x2 = x2_vec[j]
                    if not np.all(x1 == x2):
                        to_be_computed_data_pair.append((x1, x2))
                        to_be_computed_index.append((i, j))

                if use_parameterized_circuits:
                    # build parameterized circuits, it could be slower for building circuit
                    # but overall it should be faster since it only transpile one circuit
                    feature_map_params_x = ParameterVector(
                        'x', feature_map.feature_dimension)
                    feature_map_params_y = ParameterVector(
                        'y', feature_map.feature_dimension)
                    parameterized_circuit = QSVM._construct_circuit(
                        (feature_map_params_x, feature_map_params_y),
                        feature_map,
                        measurement,
                        is_statevector_sim=is_statevector_sim)
                    parameterized_circuit = quantum_instance.transpile(
                        parameterized_circuit)[0]
                    circuits = [
                        parameterized_circuit.assign_parameters({
                            feature_map_params_x:
                            x,
                            feature_map_params_y:
                            y
                        }) for x, y in to_be_computed_data_pair
                    ]
                else:
                    if logger.isEnabledFor(logging.DEBUG):
                        logger.debug("Building circuits:")
                        TextProgressBar(sys.stderr)
                    circuits = parallel_map(
                        QSVM._construct_circuit,
                        to_be_computed_data_pair,
                        task_args=(feature_map, measurement),
                        num_processes=aqua_globals.num_processes)

                results = quantum_instance.execute(
                    circuits, had_transpiled=use_parameterized_circuits)

                if logger.isEnabledFor(logging.DEBUG):
                    logger.debug("Calculating overlap:")
                    TextProgressBar(sys.stderr)
                matrix_elements = parallel_map(
                    QSVM._compute_overlap,
                    range(len(circuits)),
                    task_args=(results, is_statevector_sim, measurement_basis),
                    num_processes=aqua_globals.num_processes)

                for (i, j), value in zip(to_be_computed_index,
                                         matrix_elements):
                    mat[i, j] = value
                    if is_symmetric:
                        mat[j, i] = mat[i, j]

        if enforce_psd and is_symmetric and not is_statevector_sim:
            # Find the closest positive semi-definite approximation to kernel matrix, in case it is
            # symmetric. The (symmetric) matrix should always be positive semi-definite by
            # construction, but this can be violated in case of noise, such as sampling noise, thus,
            # the adjustment is only done if NOT using the statevector simulation.
            D, U = np.linalg.eig(mat)
            mat = U @ np.diag(np.maximum(0, D)) @ U.transpose()

        return mat
Exemplo n.º 16
0
    def construct_circuit(self, parameters, q=None):
        """
        Construct the variational form, given its parameters.

        Args:
            parameters (Union(numpy.ndarray, list[Parameter], ParameterVector)): circuit parameters
            q (QuantumRegister, optional): Quantum Register for the circuit.

        Returns:
            QuantumCircuit: a quantum circuit with given `parameters`

        Raises:
            ValueError: the number of parameters is incorrect.
        """
        if len(parameters) != self._num_parameters:
            raise ValueError('The number of parameters has to be {}'.format(
                self._num_parameters))

        if q is None:
            q = QuantumRegister(self._num_qubits, name='q')
        if self._initial_state is not None:
            circuit = self._initial_state.construct_circuit('circuit', q)
        else:
            circuit = QuantumCircuit(q)

        if logger.isEnabledFor(
                logging.DEBUG) and self._logging_construct_circuit:
            logger.debug("Evolving hopping operators:")
            TextProgressBar(sys.stderr)
            self._logging_construct_circuit = False

        num_excitations = len(self._hopping_ops)

        if not self.uccd_singlet:
            list_excitation_operators = [
                (self._hopping_ops[index % num_excitations], parameters[index])
                for index in range(self._depth * num_excitations)
            ]
        else:
            list_excitation_operators = []
            counter = 0
            for i in range(int(self._depth * self.num_groups)):
                for _ in range(
                        len(self._double_excitations_grouped[
                            i % self.num_groups])):
                    list_excitation_operators.append(
                        (self._hopping_ops[counter], parameters[i]))
                    counter += 1

        results = parallel_map(
            UCCSD._construct_circuit_for_one_excited_operator,
            list_excitation_operators,
            task_args=(q, self._num_time_slices),
            num_processes=aqua_globals.num_processes)

        for qc in results:
            if self._shallow_circuit_concat:
                circuit.data += qc.data
            else:
                circuit += qc

        return circuit
Exemplo n.º 17
0
    def construct_kernel_matrix(self, x1_vec, x2_vec=None, quantum_instance=None):
        """
        Construct kernel matrix, if x2_vec is None, self-innerproduct is conducted.

        Args:
            x1_vec (numpy.ndarray): data points, 2-D array, N1xD, where N1 is the number of data,
                                    D is the feature dimension
            x2_vec (numpy.ndarray): data points, 2-D array, N2xD, where N2 is the number of data,
                                    D is the feature dimension
            quantum_instance (QuantumInstance): quantum backend with all setting
        Returns:
            numpy.ndarray: 2-D matrix, N1xN2
        """
        self._quantum_instance = self._quantum_instance \
            if quantum_instance is None else quantum_instance
        from .qsvm import QSVM

        if x2_vec is None:
            is_symmetric = True
            x2_vec = x1_vec
        else:
            is_symmetric = False

        is_statevector_sim = self.quantum_instance.is_statevector
        measurement = not is_statevector_sim
        measurement_basis = '0' * self.num_qubits
        mat = np.ones((x1_vec.shape[0], x2_vec.shape[0]))

        # get all indices
        if is_symmetric:
            mus, nus = np.triu_indices(x1_vec.shape[0], k=1)  # remove diagonal term
        else:
            mus, nus = np.indices((x1_vec.shape[0], x2_vec.shape[0]))
            mus = np.asarray(mus.flat)
            nus = np.asarray(nus.flat)

        for idx in range(0, len(mus), QSVM.BATCH_SIZE):
            to_be_computed_list = []
            to_be_computed_index = []
            for sub_idx in range(idx, min(idx + QSVM.BATCH_SIZE, len(mus))):
                i = mus[sub_idx]
                j = nus[sub_idx]
                x1 = x1_vec[i]
                x2 = x2_vec[j]
                if not np.all(x1 == x2):
                    to_be_computed_list.append((x1, x2))
                    to_be_computed_index.append((i, j))

            if logger.isEnabledFor(logging.DEBUG):
                logger.debug("Building circuits:")
                TextProgressBar(sys.stderr)
            circuits = parallel_map(QSVM._construct_circuit,
                                    to_be_computed_list,
                                    task_args=(self.num_qubits, self.feature_map,
                                               measurement),
                                    num_processes=aqua_globals.num_processes)

            results = self.quantum_instance.execute(circuits)

            if logger.isEnabledFor(logging.DEBUG):
                logger.debug("Calculating overlap:")
                TextProgressBar(sys.stderr)
            matrix_elements = parallel_map(QSVM._compute_overlap, range(len(circuits)),
                                           task_args=(results, is_statevector_sim, measurement_basis),
                                           num_processes=aqua_globals.num_processes)

            for idx in range(len(to_be_computed_index)):
                i, j = to_be_computed_index[idx]
                mat[i, j] = matrix_elements[idx]
                if is_symmetric:
                    mat[j, i] = mat[i, j]

        return mat
    def mapping(self, map_type, threshold=0.00000001):
        """
        Map fermionic operator to qubit operator.

        Using multiprocess to speedup the mapping, the improvement can be
        observed when h2 is a non-sparse matrix.

        Args:
            map_type (str): case-insensitive mapping type.
                            "jordan_wigner", "parity", "bravyi_kitaev", "bksf"
            threshold (float): threshold for Pauli simplification

        Returns:
            PauliSumOp: create an Operator object in Paulis form.

        Raises:
            QiskitNatureError: if the `map_type` can not be recognized.
        """

        # ###################################################################
        # ###########   DEFINING MAPPED FERMIONIC OPERATORS    ##############
        # ###################################################################

        self._map_type = map_type
        n = self._modes  # number of fermionic modes / qubits
        map_type = map_type.lower()
        if map_type == 'jordan_wigner':
            a_list = self._jordan_wigner_mode(n)
        elif map_type == 'parity':
            a_list = self._parity_mode(n)
        elif map_type == 'bravyi_kitaev':
            a_list = self._bravyi_kitaev_mode(n)
        elif map_type == 'bksf':
            return bksf_mapping(self)
        else:
            raise QiskitNatureError(
                'Please specify the supported modes: '
                'jordan_wigner, parity, bravyi_kitaev, bksf')

        # ###################################################################
        # ###########    BUILDING THE MAPPED HAMILTONIAN     ################
        # ###################################################################

        pauli_list: Optional[PauliSumOp] = None
        if logger.isEnabledFor(logging.DEBUG):
            logger.debug("Mapping one-body terms to Qubit Hamiltonian:")
            TextProgressBar(output_handler=sys.stderr)
        results = parallel_map(
            FermionicOperator._one_body_mapping,
            [(self._h1[i, j], a_list[i], a_list[j])
             for i, j in itertools.product(range(n), repeat=2)
             if self._h1[i, j] != 0],
            task_args=(threshold, ),
            num_processes=algorithm_globals.num_processes)
        if results:
            pauli_list = results[0]
            for result in results[1:]:
                pauli_list += result
            # TODO: implement chop
            # pauli_list.chop(threshold=threshold)

        if logger.isEnabledFor(logging.DEBUG):
            logger.debug("Mapping two-body terms to Qubit Hamiltonian:")
            TextProgressBar(output_handler=sys.stderr)
        results = parallel_map(
            FermionicOperator._two_body_mapping,
            [(self._h2[i, j, k, m], a_list[i], a_list[j], a_list[k], a_list[m])
             for i, j, k, m in itertools.product(range(n), repeat=4)
             if self._h2[i, j, k, m] != 0],
            task_args=(threshold, ),
            num_processes=algorithm_globals.num_processes)
        if results:
            pauli_list = results[
                0] if pauli_list is None else pauli_list + results[0]
            for result in results[1:]:
                pauli_list += result
            # TODO: implement chop
            # pauli_list.chop(threshold=threshold)

        if self._ph_trans_shift is not None:
            pauli_term = ('I' * self._modes, self._ph_trans_shift)
            pauli_sum_op = PauliSumOp.from_list([pauli_term])
            pauli_list = pauli_sum_op if pauli_list is None else pauli_list + pauli_sum_op

        return pauli_list
Exemplo n.º 19
0
    def construct_circuit(self, parameters, q=None):
        """
        Construct the variational form, given its parameters.

        Args:
            parameters (Union(numpy.ndarray, list[Parameter], ParameterVector)): circuit parameters
            q (QuantumRegister, optional): Quantum Register for the circuit.

        Returns:
            QuantumCircuit: a quantum circuit with given `parameters`

        Raises:
            ValueError: the number of parameters is incorrect.
        """
        if len(parameters) != self._num_parameters:
            raise ValueError('The number of parameters has to be {}'.format(
                self._num_parameters))

        if q is None:
            q = QuantumRegister(self._num_qubits, name='q')
        if isinstance(self._initial_state, QuantumCircuit):
            circuit = QuantumCircuit(q)
            circuit.compose(self._initial_state, inplace=True)
        elif isinstance(self._initial_state, InitialState):
            circuit = self._initial_state.construct_circuit('circuit', q)
        else:
            circuit = QuantumCircuit(q)

        if logger.isEnabledFor(
                logging.DEBUG) and self._logging_construct_circuit:
            logger.debug("Evolving hopping operators:")
            TextProgressBar(sys.stderr)
            self._logging_construct_circuit = False

        num_excitations = len(self._hopping_ops)

        if not self.uccd_singlet:
            list_excitation_operators = [
                (self._hopping_ops[index % num_excitations], parameters[index])
                for index in range(self._reps * num_excitations)
            ]
        else:
            list_excitation_operators = []
            counter = 0
            for i in range(int(self._reps * self.num_groups)):
                for _ in range(
                        len(self._double_excitations_grouped[
                            i % self.num_groups])):
                    list_excitation_operators.append(
                        (self._hopping_ops[counter], parameters[i]))
                    counter += 1

        # TODO to uncomment to update for Operator flow:
        # from functools import reduce
        # ops = [(qubit_op.to_opflow().to_matrix_op() * param).exp_i()
        #        for (qubit_op, param) in list_excitation_operators]
        # circuit += reduce(lambda x, y: x @ y, reversed(ops)).to_circuit()
        # return circuit
        results = parallel_map(
            UCCSD._construct_circuit_for_one_excited_operator,
            list_excitation_operators,
            task_args=(q, self._num_time_slices),
            num_processes=aqua_globals.num_processes)

        if self._shallow_circuit_concat:
            for qc in results:
                for _, qbits, _ in qc._data:
                    for i, _ in enumerate(qbits):
                        qbits[i] = circuit.qubits[qbits[i].index]
            for qc in results:
                circuit._data += qc._data
        else:
            for qc in results:
                circuit += qc

        return circuit
Exemplo n.º 20
0
    def get_kernel_matrix(quantum_instance, feature_map, x1_vec, x2_vec=None):
        """
        Construct kernel matrix, if x2_vec is None, self-innerproduct is conducted.

        Notes:
            When using `statevector_simulator`,
            we only build the circuits for Psi(x1)|0> rather than
            Psi(x2)^dagger Psi(x1)|0>, and then we perform the inner product classically.
            That is, for `statevector_simulator`,
            the total number of circuits will be O(N) rather than
            O(N^2) for `qasm_simulator`.

        Args:
            quantum_instance (QuantumInstance): quantum backend with all settings
            feature_map (FeatureMap): a feature map that maps data to feature space
            x1_vec (numpy.ndarray): data points, 2-D array, N1xD, where N1 is the number of data,
                                    D is the feature dimension
            x2_vec (numpy.ndarray): data points, 2-D array, N2xD, where N2 is the number of data,
                                    D is the feature dimension
        Returns:
            numpy.ndarray: 2-D matrix, N1xN2
        """

        if x2_vec is None:
            is_symmetric = True
            x2_vec = x1_vec
        else:
            is_symmetric = False

        is_statevector_sim = quantum_instance.is_statevector

        measurement = not is_statevector_sim
        measurement_basis = '0' * feature_map.num_qubits
        mat = np.ones((x1_vec.shape[0], x2_vec.shape[0]))

        # get all indices
        if is_symmetric:
            mus, nus = np.triu_indices(x1_vec.shape[0],
                                       k=1)  # remove diagonal term
        else:
            mus, nus = np.indices((x1_vec.shape[0], x2_vec.shape[0]))
            mus = np.asarray(mus.flat)
            nus = np.asarray(nus.flat)

        if is_statevector_sim:
            if is_symmetric:
                to_be_computed_data = x1_vec
            else:
                to_be_computed_data = np.concatenate((x1_vec, x2_vec))

            #  the second x is redundant
            to_be_computed_data_pair = [(x, x) for x in to_be_computed_data]

            if logger.isEnabledFor(logging.DEBUG):
                logger.debug("Building circuits:")
                TextProgressBar(sys.stderr)
            circuits = parallel_map(QSVM._construct_circuit,
                                    to_be_computed_data_pair,
                                    task_args=(feature_map, measurement,
                                               is_statevector_sim),
                                    num_processes=aqua_globals.num_processes)

            results = quantum_instance.execute(circuits)

            if logger.isEnabledFor(logging.DEBUG):
                logger.debug("Calculating overlap:")
                TextProgressBar(sys.stderr)

            offset = 0 if is_symmetric else len(x1_vec)
            matrix_elements = parallel_map(
                QSVM._compute_overlap,
                list(zip(mus, nus + offset)),
                task_args=(results, is_statevector_sim, measurement_basis),
                num_processes=aqua_globals.num_processes)

            for i, j, value in zip(mus, nus, matrix_elements):
                mat[i, j] = value
                if is_symmetric:
                    mat[j, i] = mat[i, j]
        else:
            for idx in range(0, len(mus), QSVM.BATCH_SIZE):
                to_be_computed_data_pair = []
                to_be_computed_index = []
                for sub_idx in range(idx, min(idx + QSVM.BATCH_SIZE,
                                              len(mus))):
                    i = mus[sub_idx]
                    j = nus[sub_idx]
                    x1 = x1_vec[i]
                    x2 = x2_vec[j]
                    if not np.all(x1 == x2):
                        to_be_computed_data_pair.append((x1, x2))
                        to_be_computed_index.append((i, j))

                if logger.isEnabledFor(logging.DEBUG):
                    logger.debug("Building circuits:")
                    TextProgressBar(sys.stderr)
                circuits = parallel_map(
                    QSVM._construct_circuit,
                    to_be_computed_data_pair,
                    task_args=(feature_map, measurement),
                    num_processes=aqua_globals.num_processes)

                results = quantum_instance.execute(circuits)

                if logger.isEnabledFor(logging.DEBUG):
                    logger.debug("Calculating overlap:")
                    TextProgressBar(sys.stderr)
                matrix_elements = parallel_map(
                    QSVM._compute_overlap,
                    range(len(circuits)),
                    task_args=(results, is_statevector_sim, measurement_basis),
                    num_processes=aqua_globals.num_processes)

                for (i, j), value in zip(to_be_computed_index,
                                         matrix_elements):
                    mat[i, j] = value
                    if is_symmetric:
                        mat[j, i] = mat[i, j]

        return mat