Ejemplo n.º 1
0
    def __init__(
        self,
        qubit_converter: QubitConverter,
        solver: MinimumEigensolverFactory,
        threshold: float = 1e-5,
        delta: float = 1,
        max_iterations: Optional[int] = None,
    ) -> None:
        """
        Args:
            qubit_converter: a class that converts second quantized operator to qubit operator
            solver: a factory for the VQE solver employing a UCCSD ansatz.
            threshold: the energy convergence threshold. It has a minimum value of 1e-15.
            delta: the finite difference step size for the gradient computation. It has a minimum
                value of 1e-5.
            max_iterations: the maximum number of iterations of the AdaptVQE algorithm.
        """
        validate_min('threshold', threshold, 1e-15)
        validate_min('delta', delta, 1e-5)

        super().__init__(qubit_converter, solver)

        self._threshold = threshold
        self._delta = delta
        self._max_iterations = max_iterations

        self._excitation_pool: List[OperatorBase] = []
        self._excitation_list: List[OperatorBase] = []

        self._main_operator: PauliSumOp = None
        self._ansatz: QuantumCircuit = None
Ejemplo n.º 2
0
def hartree_fock_bitstring(num_spin_orbitals: int,
                           num_particles: tuple[int, int]) -> list[bool]:
    """Compute the bitstring representing the Hartree-Fock state for the specified system.

    Args:
        num_spin_orbitals: The number of spin orbitals, has a min. value of 1.
        num_particles: The number of particles as a tuple storing the number of alpha- and beta-spin
                       electrons in the first and second number, respectively.

    Returns:
        The bitstring representing the state of the Hartree-Fock state as array of bools.

    Raises:
        ValueError: If the total number of particles is larger than the number of orbitals.
    """
    # validate the input
    validate_min("num_spin_orbitals", num_spin_orbitals, 1)
    num_alpha, num_beta = num_particles

    if sum(num_particles) > num_spin_orbitals:
        raise ValueError(
            "# of particles must be less than or equal to # of orbitals.")

    half_orbitals = num_spin_orbitals // 2
    bitstr = np.zeros(num_spin_orbitals, bool)
    bitstr[:num_alpha] = True
    bitstr[half_orbitals:(half_orbitals + num_beta)] = True

    return bitstr.tolist()
Ejemplo n.º 3
0
 def __init__(self,
              maxfun: int = 1000,
              factr: float = 10,
              iprint: int = -1,
              max_processes: Optional[int] = None) -> None:
     r"""
     Args:
         maxfun: Maximum number of function evaluations.
         factr : The iteration stops when (f\^k - f\^{k+1})/max{\|f\^k\|,
             \|f\^{k+1}|,1} <= factr * eps, where eps is the machine precision,
             which is automatically generated by the code. Typical values for
             factr are: 1e12 for low accuracy; 1e7 for moderate accuracy;
             10.0 for extremely high accuracy. See Notes for relationship to ftol,
             which is exposed (instead of factr) by the scipy.optimize.minimize
             interface to L-BFGS-B.
         iprint: Controls the frequency of output. iprint < 0 means no output;
             iprint = 0 print only one line at the last iteration; 0 < iprint < 99
             print also f and \|proj g\| every iprint iterations; iprint = 99 print
             details of every iteration except n-vectors; iprint = 100 print also the
             changes of active set and final x; iprint > 100 print details of
             every iteration including x and g.
         max_processes: maximum number of processes allowed, has a min. value of 1 if not None.
     """
     if max_processes:
         validate_min('max_processes', max_processes, 1)
     super().__init__()
     for k, v in list(locals().items()):
         if k in self._OPTIONS:
             self._options[k] = v
     self._max_processes = max_processes
Ejemplo n.º 4
0
    def __init__(
        self,
        k: int = 1,
        filter_criterion: Callable[
            [Union[List,
                   np.ndarray], float, Optional[List[float]]], bool] = None
    ) -> None:
        """
        Args:
            k: How many eigenvalues are to be computed, has a min. value of 1.
            filter_criterion: callable that allows to filter eigenvalues/eigenstates, only feasible
                eigenstates are returned in the results. The callable has the signature
                `filter(eigenstate, eigenvalue, aux_values)` and must return a boolean to indicate
                whether to keep this value in the final returned result or not. If the number of
                elements that satisfies the criterion is smaller than `k` then the returned list has
                fewer elements and can even be empty.
        """
        validate_min('k', k, 1)
        super().__init__()

        self._in_k = k
        self._k = k

        self._filter_criterion = filter_criterion

        self._ret = EigensolverResult()
Ejemplo n.º 5
0
 def __init__(self,
              maxiter: int = 1000,
              save_steps: int = 1,
              last_avg: int = 1,
              c0: float = _C0,
              c1: float = 0.1,
              c2: float = 0.602,
              c3: float = 0.101,
              c4: float = 0,
              skip_calibration: bool = False) -> None:
     """
     Args:
         maxiter: Maximum number of iterations to perform.
         save_steps: Save intermediate info every save_steps step. It has a min. value of 1.
         last_avg: Averaged parameters over the last_avg iterations.
             If last_avg = 1, only the last iteration is considered. It has a min. value of 1.
         c0: The initial a. Step size to update parameters.
         c1: The initial c. The step size used to approximate gradient.
         c2: The alpha in the paper, and it is used to adjust a (c0) at each iteration.
         c3: The gamma in the paper, and it is used to adjust c (c1) at each iteration.
         c4: The parameter used to control a as well.
         skip_calibration: Skip calibration and use provided c(s) as is.
     """
     validate_min('save_steps', save_steps, 1)
     validate_min('last_avg', last_avg, 1)
     super().__init__()
     for k, v in list(locals().items()):
         if k in self._OPTIONS:
             self._options[k] = v
     self._maxiter = maxiter
     self._parameters = np.array([c0, c1, c2, c3, c4])
     self._skip_calibration = skip_calibration
Ejemplo n.º 6
0
    def __init__(
        self,
        method: Union[str, Callable],
        options: Optional[Dict[str, Any]] = None,
        max_evals_grouped: int = 1,
        **kwargs,
    ):
        """
        Args:
            method: Type of solver.
            options: A dictionary of solver options.
            kwargs: additional kwargs for scipy.optimize.minimize.
            max_evals_grouped: Max number of default gradient evaluations performed simultaneously.
        """
        # pylint: disable=super-init-not-called
        self._method = method.lower() if isinstance(method, str) else method
        # Set support level
        if self._method in self._bounds_support_methods:
            self._bounds_support_level = OptimizerSupportLevel.supported
        else:
            self._bounds_support_level = OptimizerSupportLevel.ignored
        if self._method in self._gradient_support_methods:
            self._gradient_support_level = OptimizerSupportLevel.supported
        else:
            self._gradient_support_level = OptimizerSupportLevel.ignored
        self._initial_point_support_level = OptimizerSupportLevel.required

        self._options = options if options is not None else {}
        validate_min("max_evals_grouped", max_evals_grouped, 1)
        self._max_evals_grouped = max_evals_grouped
        self._kwargs = kwargs
Ejemplo n.º 7
0
    def __init__(
        self,
        atoms: Union[str, List[str]] = "H 0.0 0.0 0.0; H 0.0 0.0 0.735",
        units: UnitsType = UnitsType.ANGSTROM,
        charge: int = 0,
        multiplicity: int = 1,
        basis: BasisType = BasisType.BSTO3G,
        method: MethodType = MethodType.RHF,
        tol: float = 1e-8,
        maxiters: int = 100,
    ) -> None:
        """
        Args:
            atoms: Atoms list or string separated by semicolons or line breaks. Each element in the
                list is an atom followed by position e.g. `H 0.0 0.0 0.5`. The preceding example
                shows the `XYZ` format for position but `Z-Matrix` format is supported too here.
            units: Angstrom or Bohr.
            charge: Charge on the molecule.
            multiplicity: Spin multiplicity (2S+1)
            basis: Basis set; sto3g, 6-31g or 6-31g**
            method: Hartree-Fock Method type.
            tol: Convergence tolerance see pyquante2.scf hamiltonians and iterators
            maxiters: Convergence max iterations see pyquante2.scf hamiltonians and iterators,
                has a min. value of 1.

        Raises:
            QiskitNatureError: Invalid Input
        """
        super().__init__()
        # pylint: disable=import-error
        from pyquante2 import molecule as pyquante_molecule
        from pyquante2 import rhf, uhf, rohf, basisset

        validate_min("maxiters", maxiters, 1)
        PyQuanteDriver.check_method_supported(method)
        if not isinstance(atoms, str) and not isinstance(atoms, list):
            raise QiskitNatureError(
                f"Invalid atom input for PYQUANTE Driver '{atoms}'")

        if isinstance(atoms, list):
            atoms = ";".join(atoms)
        elif isinstance(atoms, str):
            atoms = atoms.replace("\n", ";")

        self._atoms = atoms
        self._units = units
        self._charge = charge
        self._multiplicity = multiplicity
        self._basis = basis
        self._method = method
        self._tol = tol
        self._maxiters = maxiters

        self._mol: pyquante_molecule = None
        self._bfs: basisset = None
        self._calc: Union[rhf, rohf, uhf] = None
        self._nmo: int = None
Ejemplo n.º 8
0
    def __init__(
        self,
        atoms: Union[str, List[str]] = "H 0.0 0.0 0.0; H 0.0 0.0 0.735",
        units: UnitsType = UnitsType.ANGSTROM,
        charge: int = 0,
        multiplicity: int = 1,
        basis: BasisType = BasisType.BSTO3G,
        hf_method: HFMethodType = HFMethodType.RHF,
        tol: float = 1e-8,
        maxiters: int = 100,
        molecule: Optional[Molecule] = None,
    ) -> None:
        """
        Args:
            atoms: Atoms list or string separated by semicolons or line breaks. Each element in the
                list is an atom followed by position e.g. `H 0.0 0.0 0.5`. The preceding example
                shows the `XYZ` format for position but `Z-Matrix` format is supported too here.
            units: Angstrom or Bohr.
            charge: Charge on the molecule.
            multiplicity: Spin multiplicity (2S+1)
            basis: Basis set; sto3g, 6-31g or 6-31g**
            hf_method: Hartree-Fock Method type.
            tol: Convergence tolerance see pyquante2.scf hamiltonians and iterators
            maxiters: Convergence max iterations see pyquante2.scf hamiltonians and iterators,
                has a min. value of 1.
            molecule: A driver independent Molecule definition instance may be provided. When a
                molecule is supplied the ``atoms``, ``units``, ``charge`` and ``multiplicity``
                parameters are all ignored as the Molecule instance now defines these instead. The
                Molecule object is read when the driver is run and converted to the driver dependent
                configuration for the computation. This allows, for example, the Molecule geometry
                to be updated to compute different points.

        Raises:
            QiskitNatureError: Invalid Input
        """
        validate_min("maxiters", maxiters, 1)
        self._check_valid()
        if not isinstance(atoms, str) and not isinstance(atoms, list):
            raise QiskitNatureError("Invalid atom input for PYQUANTE Driver '{}'".format(atoms))

        if isinstance(atoms, list):
            atoms = ";".join(atoms)
        elif isinstance(atoms, str):
            atoms = atoms.replace("\n", ";")

        super().__init__(
            molecule=molecule,
            basis=basis.value,
            hf_method=hf_method.value,
            supports_molecule=True,
        )
        self._atoms = atoms
        self._units = units.value
        self._charge = charge
        self._multiplicity = multiplicity
        self._tol = tol
        self._maxiters = maxiters
Ejemplo n.º 9
0
 def __init__(
     self,
     maxfun: int = 1000,
     ftol: float = 10 * np.finfo(float).eps,
     factr: Optional[float] = None,
     iprint: int = -1,
     max_processes: Optional[int] = None,
     options: Optional[dict] = None,
     max_evals_grouped: int = 1,
     **kwargs,
 ) -> None:
     r"""
     Args:
         maxfun: Maximum number of function evaluations.
         ftol: The iteration stops when (f\^k - f\^{k+1})/max{\|f\^k\|,\|f\^{k+1}\|,1} <= ftol.
         factr : (DEPRECATED) The iteration stops when (f\^k - f\^{k+1})/max{\|f\^k\|,
             \|f\^{k+1}|,1} <= factr * eps, where eps is the machine precision,
             which is automatically generated by the code. Typical values for
             factr are: 1e12 for low accuracy; 1e7 for moderate accuracy;
             10.0 for extremely high accuracy. See Notes for relationship to ftol,
             which is exposed (instead of factr) by the scipy.optimize.minimize
             interface to L-BFGS-B.
         iprint: Controls the frequency of output. iprint < 0 means no output;
             iprint = 0 print only one line at the last iteration; 0 < iprint < 99
             print also f and \|proj g\| every iprint iterations; iprint = 99 print
             details of every iteration except n-vectors; iprint = 100 print also the
             changes of active set and final x; iprint > 100 print details of
             every iteration including x and g.
         max_processes: maximum number of processes allowed, has a min. value of 1 if not None.
         options: A dictionary of solver options.
         max_evals_grouped: Max number of default gradient evaluations performed simultaneously.
         kwargs: additional kwargs for scipy.optimize.minimize.
     """
     if max_processes:
         validate_min("max_processes", max_processes, 1)
     if factr is not None:
         warnings.warn(
             "P_BFGS.__init__() keyword argument factr is deprecated and replaced with ftol. "
             "The relationship between the two is ftol = factr * numpy.finfo(float).eps. "
             "See https://docs.scipy.org/doc/scipy/reference/optimize.minimize-lbfgsb.html.",
             DeprecationWarning,
             stacklevel=2,
         )
         ftol = factr * np.finfo(float).eps
     if options is None:
         options = {}
     for k, v in list(locals().items()):
         if k in self._OPTIONS:
             options[k] = v
     super().__init__(
         method="L-BFGS-B",
         options=options,
         max_evals_grouped=max_evals_grouped,
         **kwargs,
     )
     self._max_processes = max_processes
Ejemplo n.º 10
0
    def __init__(
        self,
        N: int = 15,
        a: int = 2,
        quantum_instance: Optional[Union[QuantumInstance, BaseBackend,
                                         Backend]] = None
    ) -> None:
        """
        Args:
            N: The integer to be factored, has a min. value of 3.
            a: Any integer that satisfies 1 < a < N and gcd(a, N) = 1.
            quantum_instance: Quantum Instance or Backend

         Raises:
            ValueError: Invalid input
        """
        validate_min('N', N, 3)
        validate_min('a', a, 2)
        super().__init__(quantum_instance)
        self._n = None  # type: Optional[int]
        self._up_qreg = None
        self._down_qreg = None  # type: Optional[QuantumRegister]
        self._aux_qreg = None  # type: Optional[QuantumRegister]

        # check the input integer
        if N < 1 or N % 2 == 0:
            raise ValueError(
                'The input needs to be an odd integer greater than 1.')

        self._N = N

        if a >= N or math.gcd(a, self._N) != 1:
            raise ValueError(
                'The integer a needs to satisfy a < N and gcd(a, N) = 1.')

        self._a = a

        self._ret = AlgorithmResult({
            "factors": [],
            "total_counts": 0,
            "successful_counts": 0
        })

        # check if the input integer is a power
        tf, b, p = is_power(N, return_decomposition=True)
        if tf:
            logger.info('The input integer is a power: %s=%s^%s.', N, b, p)
            self._ret['factors'].append(b)

        self._qft = QFT(do_swaps=False).to_instruction()
        self._iqft = self._qft.inverse()

        self._phi_add_N = None  # type: Optional[Gate]
        self._iphi_add_N = None
Ejemplo n.º 11
0
    def _validate_input(a: int, N: int):
        validate_min('N', N, 3)
        validate_min('a', a, 2)

        if N < 1 or N % 2 == 0:
            raise ValueError(
                f'The input N needs to be an odd integer greater than 1. Provided N = {N}.'
            )
        if a >= N or math.gcd(a, N) != 1:
            raise ValueError(
                f'The integer a needs to satisfy a < N and gcd(a, N) = 1. Provided a = {a}.'
            )
Ejemplo n.º 12
0
 def __init__(self, code_size: int = 4):
     """
     Args:
         code_size: Size of error correcting code
     """
     validate_min('code_size', code_size, 1)
     super().__init__()
     self.code_size = code_size
     self.rand = algorithm_globals.random
     self.estimators = None
     self.classes = None
     self.codebook = None
    def __init__(
        self,
        optimizer: OptimizationAlgorithm,
        min_num_vars: int = 1,
        min_num_vars_optimizer: Optional[OptimizationAlgorithm] = None,
        penalty: Optional[float] = None,
        history: Optional[IntermediateResult] = IntermediateResult.
        LAST_ITERATION,
        converters: Optional[Union[QuadraticProgramConverter,
                                   List[QuadraticProgramConverter]]] = None,
    ) -> None:
        """Initializes the recursive minimum eigen optimizer.

        This initializer takes an ``OptimizationAlgorithm``, the parameters to specify until when to
        to apply the iterative scheme, and the optimizer to be applied once the threshold number of
        variables is reached.

        Args:
            optimizer: The optimizer to use in every iteration.
            min_num_vars: The minimum number of variables to apply the recursive scheme. If this
                threshold is reached, the min_num_vars_optimizer is used.
            min_num_vars_optimizer: This optimizer is used after the recursive scheme for the
                problem with the remaining variables. Default value is
                :class:`~qiskit_optimization.algorithms.MinimumEigenOptimizer` created on top of
                :class:`~qiskit.algorithms.minimum_eigen_solver.NumPyMinimumEigensolver`.
            penalty: The factor that is used to scale the penalty terms corresponding to linear
                equality constraints.
            history: Whether the intermediate results are stored.
                Default value is :py:obj:`~IntermediateResult.LAST_ITERATION`.
            converters: The converters to use for converting a problem into a different form.
                By default, when None is specified, an internally created instance of
                :class:`~qiskit_optimization.converters.QuadraticProgramToQubo` will be used.

        Raises:
            QiskitOptimizationError: In case of invalid parameters (num_min_vars < 1).
            TypeError: When there one of converters is an invalid type.
        """

        validate_min("min_num_vars", min_num_vars, 1)

        self._optimizer = optimizer
        self._min_num_vars = min_num_vars
        if min_num_vars_optimizer:
            self._min_num_vars_optimizer = min_num_vars_optimizer
        else:
            self._min_num_vars_optimizer = MinimumEigenOptimizer(
                NumPyMinimumEigensolver())
        self._penalty = penalty
        self._history = history

        self._converters = self._prepare_converters(converters, penalty)
Ejemplo n.º 14
0
def _check_deprecated_args(mct_mode, rotation_counts, lam, num_iterations):
    """Check the deprecated args."""

    if mct_mode is not None:
        validate_in_set(
            'mct_mode', mct_mode,
            {'basic', 'basic-dirty-ancilla', 'advanced', 'noancilla'})
        warnings.warn(
            'The mct_mode argument is deprecated as of 0.8.0, and will be removed no '
            'earlier than 3 months after the release date. If you want to use a '
            'special MCX mode you should use the GroverOperator in '
            'qiskit.circuit.library directly and pass it to the grover_operator '
            'keyword argument.',
            DeprecationWarning,
            stacklevel=3)

    if rotation_counts is not None:
        warnings.warn(
            'The rotation_counts argument is deprecated as of 0.8.0, and will be '
            'removed no earlier than 3 months after the release date. '
            'If you want to use the incremental mode with the rotation_counts '
            'argument or you should use the iterations argument instead and pass '
            'a list of integers',
            DeprecationWarning,
            stacklevel=3)

    if lam is not None:
        warnings.warn(
            'The lam argument is deprecated as of 0.8.0, and will be '
            'removed no earlier than 3 months after the release date. '
            'If you want to use the incremental mode with the lam argument, '
            'you should use the iterations argument instead and pass '
            'a list of integers calculated with the lam argument.',
            DeprecationWarning,
            stacklevel=3)

    if num_iterations is not None:
        validate_min('num_iterations', num_iterations, 1)
        warnings.warn(
            'The num_iterations argument is deprecated as of 0.8.0, and will be '
            'removed no earlier than 3 months after the release date. '
            'If you want to use the num_iterations argument '
            'you should use the iterations argument instead and pass an integer '
            'for the number of iterations.',
            DeprecationWarning,
            stacklevel=3)
Ejemplo n.º 15
0
    def _validate_input(N: int, a: int):
        """Check parameters of the algorithm.

        Args:
            N: The odd integer to be factored, has a min. value of 3.
            a: Any integer that satisfies 1 < a < N and gcd(a, N) = 1.

        Raises:
            ValueError: Invalid input

        """
        validate_min("N", N, 3)
        validate_min("a", a, 2)

        if N < 1 or N % 2 == 0:
            raise ValueError("The input needs to be an odd integer greater than 1.")

        if a >= N or math.gcd(a, N) != 1:
            raise ValueError("The integer a needs to satisfy a < N and gcd(a, N) = 1.")
Ejemplo n.º 16
0
 def __init__(self,
              maxiter: int = 1000,
              save_steps: int = 1,
              last_avg: int = 1,
              c0: float = _C0,
              c1: float = 0.1,
              c2: float = 0.602,
              c3: float = 0.101,
              c4: float = 0,
              skip_calibration: bool = False,
              max_trials: Optional[int] = None) -> None:
     """
     Args:
         maxiter: Maximum number of iterations to perform.
         save_steps: Save intermediate info every save_steps step. It has a min. value of 1.
         last_avg: Averaged parameters over the last_avg iterations.
             If last_avg = 1, only the last iteration is considered. It has a min. value of 1.
         c0: The initial a. Step size to update parameters.
         c1: The initial c. The step size used to approximate gradient.
         c2: The alpha in the paper, and it is used to adjust a (c0) at each iteration.
         c3: The gamma in the paper, and it is used to adjust c (c1) at each iteration.
         c4: The parameter used to control a as well.
         skip_calibration: Skip calibration and use provided c(s) as is.
         max_trials: Deprecated, use maxiter.
     """
     validate_min('save_steps', save_steps, 1)
     validate_min('last_avg', last_avg, 1)
     super().__init__()
     if max_trials is not None:
         warnings.warn(
             'The max_trials parameter is deprecated as of '
             '0.8.0 and will be removed no sooner than 3 months after the release. '
             'You should use maxiter instead.', DeprecationWarning)
         maxiter = max_trials
     for k, v in list(locals().items()):
         if k in self._OPTIONS:
             self._options[k] = v
     self._maxiter = maxiter
     self._parameters = np.array([c0, c1, c2, c3, c4])
     self._skip_calibration = skip_calibration
Ejemplo n.º 17
0
    def __init__(
        self,
        maxfun: int = 1000,
        ftol: float = 10 * np.finfo(float).eps,
        iprint: int = -1,
        max_processes: Optional[int] = None,
        options: Optional[dict] = None,
        max_evals_grouped: int = 1,
        **kwargs,
    ) -> None:
        r"""
        Args:
            maxfun: Maximum number of function evaluations.
            ftol: The iteration stops when (f\^k - f\^{k+1})/max{\|f\^k\|,\|f\^{k+1}\|,1} <= ftol.
            iprint: Controls the frequency of output. iprint < 0 means no output;
                iprint = 0 print only one line at the last iteration; 0 < iprint < 99
                print also f and \|proj g\| every iprint iterations; iprint = 99 print
                details of every iteration except n-vectors; iprint = 100 print also the
                changes of active set and final x; iprint > 100 print details of
                every iteration including x and g.
            max_processes: maximum number of processes allowed, has a min. value of 1 if not None.
            options: A dictionary of solver options.
            max_evals_grouped: Max number of default gradient evaluations performed simultaneously.
            kwargs: additional kwargs for scipy.optimize.minimize.
        """
        if max_processes:
            validate_min("max_processes", max_processes, 1)

        if options is None:
            options = {}
        for k, v in list(locals().items()):
            if k in self._OPTIONS:
                options[k] = v
        super().__init__(
            method="L-BFGS-B",
            options=options,
            max_evals_grouped=max_evals_grouped,
            **kwargs,
        )
        self._max_processes = max_processes
Ejemplo n.º 18
0
    def __init__(
        self,
        operator: Optional[Union[OperatorBase, LegacyBaseOperator]] = None,
        k: int = 1,
        aux_operators: Optional[List[Optional[Union[
            OperatorBase, LegacyBaseOperator]]]] = None,
        filter_criterion: Callable[
            [Union[List,
                   np.ndarray], float, Optional[List[float]]], bool] = None
    ) -> None:
        """
        Args:
            operator: Operator instance. If None is supplied it must be provided later before
                run() is called. Allowing None here permits the algorithm to be configured
                and used later when operator is available, say creating an instance an letting
                application stack use this algorithm with an operator it creates.
            k: How many eigenvalues are to be computed, has a min. value of 1.
            aux_operators: Auxiliary operators to be evaluated at each eigenvalue
            filter_criterion: callable that allows to filter eigenvalues/eigenstates, only feasible
                eigenstates are returned in the results. The callable has the signature
                `filter(eigenstate, eigenvalue, aux_values)` and must return a boolean to indicate
                whether to keep this value in the final returned result or not. If the number of
                elements that satisfies the criterion is smaller than `k` then the returned list has
                fewer elements and can even be empty.
        """
        validate_min('k', k, 1)
        super().__init__()

        self._operator = None
        self._aux_operators = None
        self._in_k = k
        self._k = k

        self.operator = operator
        self.aux_operators = aux_operators

        self._filter_criterion = filter_criterion

        self._ret = {}  # type: Dict[str, Any]
Ejemplo n.º 19
0
    def __init__(self,
                 transformation: FermionicTransformation,
                 solver: MinimumEigensolverFactory,
                 threshold: float = 1e-5,
                 delta: float = 1,
                 max_iterations: Optional[int] = None,
                 ) -> None:
        """
        Args:
            transformation: a fermionic driver to operator transformation strategy.
            solver: a factory for the VQE solver employing a UCCSD variational form.
            threshold: the energy convergence threshold. It has a minimum value of 1e-15.
            delta: the finite difference step size for the gradient computation. It has a minimum
                value of 1e-5.
            max_iterations: the maximum number of iterations of the AdaptVQE algorithm.
        """
        validate_min('threshold', threshold, 1e-15)
        validate_min('delta', delta, 1e-5)

        super().__init__(transformation, solver)

        self._threshold = threshold
        self._delta = delta
        self._max_iterations = max_iterations
Ejemplo n.º 20
0
 def test_validate_min(self):
     """validate min test"""
     test_value = 2.5
     validate_min("test_value", test_value, -1)
     validate_min("test_value", test_value, 2.5)
     with self.assertRaises(ValueError):
         validate_min("test_value", test_value, 4)
     validate_min_exclusive("test_value", test_value, -1)
     with self.assertRaises(ValueError):
         validate_min_exclusive("test_value", test_value, 2.5)
     with self.assertRaises(ValueError):
         validate_min_exclusive("test_value", test_value, 4)
Ejemplo n.º 21
0
    def __init__(
        self,
        ansatz: Optional[QuantumCircuit] = None,
        optimizer: Optional[Optimizer] = None,
        initial_point: Optional[np.ndarray] = None,
        gradient: Optional[Union[GradientBase, Callable]] = None,
        expectation: Optional[ExpectationBase] = None,
        include_custom: bool = False,
        max_evals_grouped: int = 1,
        callback: Optional[Callable[[int, np.ndarray, float, float],
                                    None]] = None,
        quantum_instance: Optional[Union[QuantumInstance, BaseBackend,
                                         Backend]] = None,
        sort_parameters_by_name: Optional[bool] = None,
    ) -> None:
        """

        Args:
            ansatz: A parameterized circuit used as Ansatz for the wave function.
            optimizer: A classical optimizer.
            initial_point: An optional initial point (i.e. initial parameter values)
                for the optimizer. If ``None`` then VQE will look to the ansatz for a preferred
                point and if not will simply compute a random one.
            gradient: An optional gradient function or operator for optimizer.
            expectation: The Expectation converter for taking the average value of the
                Observable over the ansatz state function. When ``None`` (the default) an
                :class:`~qiskit.opflow.expectations.ExpectationFactory` is used to select
                an appropriate expectation based on the operator and backend. When using Aer
                qasm_simulator backend, with paulis, it is however much faster to leverage custom
                Aer function for the computation but, although VQE performs much faster
                with it, the outcome is ideal, with no shot noise, like using a state vector
                simulator. If you are just looking for the quickest performance when choosing Aer
                qasm_simulator and the lack of shot noise is not an issue then set `include_custom`
                parameter here to ``True`` (defaults to ``False``).
            include_custom: When `expectation` parameter here is None setting this to ``True`` will
                allow the factory to include the custom Aer pauli expectation.
            max_evals_grouped: Max number of evaluations performed simultaneously. Signals the
                given optimizer that more than one set of parameters can be supplied so that
                potentially the expectation values can be computed in parallel. Typically this is
                possible when a finite difference gradient is used by the optimizer such that
                multiple points to compute the gradient can be passed and if computed in parallel
                improve overall execution time. Deprecated if a gradient operator or function is
                given.
            callback: a callback that can access the intermediate data during the optimization.
                Four parameter values are passed to the callback as follows during each evaluation
                by the optimizer for its current set of parameters as it works towards the minimum.
                These are: the evaluation count, the optimizer parameters for the
                ansatz, the evaluated mean and the evaluated standard deviation.`
            quantum_instance: Quantum Instance or Backend
            sort_parameters_by_name: Deprecated. If True, the initial point is bound to the ansatz
                parameters strictly sorted by name instead of the default circuit order. That means
                that the ansatz parameters are e.g. sorted as ``x[0] x[1] x[10] x[2] ...`` instead
                of ``x[0] x[1] x[2] ... x[10]``. Set this to ``True`` to obtain the behavior prior
                to Qiskit Terra 0.18.0.
        """
        validate_min("max_evals_grouped", max_evals_grouped, 1)

        if sort_parameters_by_name is not None:
            warnings.warn(
                "The ``sort_parameters_by_name`` attribute is deprecated and will be "
                "removed no sooner than 3 months after the release date of Qiskit Terra "
                "0.18.0.",
                DeprecationWarning,
                stacklevel=2,
            )

        if ansatz is None:
            ansatz = RealAmplitudes()

        if optimizer is None:
            optimizer = SLSQP()

        if quantum_instance is not None:
            if not isinstance(quantum_instance, QuantumInstance):
                quantum_instance = QuantumInstance(quantum_instance)

        super().__init__()

        self._max_evals_grouped = max_evals_grouped
        self._circuit_sampler = None  # type: Optional[CircuitSampler]
        self._expectation = expectation
        self._include_custom = include_custom

        # set ansatz -- still supporting pre 0.18.0 sorting
        self._sort_parameters_by_name = sort_parameters_by_name
        self._ansatz_params = None
        self._ansatz = None
        self.ansatz = ansatz

        self._optimizer = optimizer
        self._initial_point = initial_point
        self._gradient = gradient
        self._quantum_instance = None

        if quantum_instance is not None:
            self.quantum_instance = quantum_instance

        self._eval_time = None
        self._eval_count = 0
        self._optimizer.set_max_evals_grouped(max_evals_grouped)
        self._callback = callback

        logger.info(self.print_settings())

        # TODO remove this once the stateful methods are deleted
        self._ret = None
Ejemplo n.º 22
0
    def __init__(
        self,
        optimizer: Optional[Union[Optimizer, Minimizer]] = None,
        reps: int = 1,
        initial_state: Optional[QuantumCircuit] = None,
        mixer: Union[QuantumCircuit, OperatorBase] = None,
        initial_point: Optional[np.ndarray] = None,
        gradient: Optional[Union[GradientBase, Callable[[Union[np.ndarray, List]], List]]] = None,
        expectation: Optional[ExpectationBase] = None,
        include_custom: bool = False,
        max_evals_grouped: int = 1,
        callback: Optional[Callable[[int, np.ndarray, float, float], None]] = None,
        quantum_instance: Optional[Union[QuantumInstance, Backend]] = None,
    ) -> None:
        """
        Args:
            optimizer: A classical optimizer, see also :class:`~qiskit.algorithms.VQE` for
                more details on the possible types.
            reps: the integer parameter :math:`p` as specified in https://arxiv.org/abs/1411.4028,
                Has a minimum valid value of 1.
            initial_state: An optional initial state to prepend the QAOA circuit with
            mixer: the mixer Hamiltonian to evolve with or a custom quantum circuit. Allows support
                of optimizations in constrained subspaces as per https://arxiv.org/abs/1709.03489
                as well as warm-starting the optimization as introduced
                in http://arxiv.org/abs/2009.10095.
            initial_point: An optional initial point (i.e. initial parameter values)
                for the optimizer. If ``None`` then it will simply compute a random one.
            gradient: An optional gradient operator respectively a gradient function used for
                      optimization.
            expectation: The Expectation converter for taking the average value of the
                Observable over the ansatz state function. When None (the default) an
                :class:`~qiskit.opflow.expectations.ExpectationFactory` is used to select
                an appropriate expectation based on the operator and backend. When using Aer
                qasm_simulator backend, with paulis, it is however much faster to leverage custom
                Aer function for the computation but, although VQE performs much faster
                with it, the outcome is ideal, with no shot noise, like using a state vector
                simulator. If you are just looking for the quickest performance when choosing Aer
                qasm_simulator and the lack of shot noise is not an issue then set `include_custom`
                parameter here to True (defaults to False).
            include_custom: When `expectation` parameter here is None setting this to True will
                allow the factory to include the custom Aer pauli expectation.
            max_evals_grouped: Max number of evaluations performed simultaneously. Signals the
                given optimizer that more than one set of parameters can be supplied so that
                potentially the expectation values can be computed in parallel. Typically this is
                possible when a finite difference gradient is used by the optimizer such that
                multiple points to compute the gradient can be passed and if computed in parallel
                improve overall execution time. Ignored if a gradient operator or function is
                given.
            callback: a callback that can access the intermediate data during the optimization.
                Four parameter values are passed to the callback as follows during each evaluation
                by the optimizer for its current set of parameters as it works towards the minimum.
                These are: the evaluation count, the optimizer parameters for the
                ansatz, the evaluated mean and the evaluated standard deviation.
            quantum_instance: Quantum Instance or Backend
        """
        validate_min("reps", reps, 1)

        self._reps = reps
        self._mixer = mixer
        self._initial_state = initial_state
        self._cost_operator = None

        super().__init__(
            ansatz=None,
            optimizer=optimizer,
            initial_point=initial_point,
            gradient=gradient,
            expectation=expectation,
            include_custom=include_custom,
            max_evals_grouped=max_evals_grouped,
            callback=callback,
            quantum_instance=quantum_instance,
        )
Ejemplo n.º 23
0
    def __init__(
        self,
        data: Union[
            str,
            List[Tuple[str, complex]],
            Tuple[np.ndarray, np.ndarray],
        ],
        spin: Union[float, Fraction] = Fraction(1, 2),
        register_length: Optional[int] = None,
    ):
        r"""
        Args:
            data: label string, list of labels and coefficients. See the label section in
                  the documentation of :class:`SpinOp` for more details.
            spin: positive half-integer (integer or half-odd-integer) that represents spin.
            register_length: length of the particle register.

        Raises:
            ValueError: invalid data is given.
            QiskitNatureError: invalid spin value
        """
        self._coeffs: np.ndarray
        self._spin_array: np.ndarray
        dtype = np.complex128  # TODO: configurable data type. mixin?

        spin = Fraction(spin)
        if spin.denominator not in (1, 2):
            raise QiskitNatureError(
                f"spin must be a positive half-integer (integer or half-odd-integer), not {spin}."
            )
        self._dim = int(2 * spin + 1)

        if isinstance(data, tuple) and all(isinstance(datum, np.ndarray) for datum in data):
            self._spin_array = np.array(data[0], dtype=np.uint8)
            self._register_length = self._spin_array.shape[2]
            self._coeffs = np.array(data[1], dtype=dtype)

        if (
            isinstance(data, tuple)
            and isinstance(data[0], str)
            and isinstance(data[1], (int, float, complex))
        ):
            data = [data]

        if isinstance(data, str):
            data = [(data, 1)]

        if isinstance(data, list):
            if register_length is not None:  # Sparse label
                # [IXYZ]_index^power (power is optional) or [+-]_index
                sparse = r"([IXYZ]_\d+(\^\d+)?|[\+\-]_\d+?)"
                # space (\s) separated sparse label or empty string
                label_pattern = re.compile(rf"^({sparse}\s)*{sparse}(?!\s)$|^$")
                invalid_labels = [label for label, _ in data if not label_pattern.match(label)]
                if invalid_labels:
                    raise ValueError(f"Invalid labels for sparse labels: {invalid_labels}.")
            else:  # dense_label
                # dense label (repeat of [IXYZ+-])
                label_pattern = re.compile(r"^[IXYZ\+\-]+$")
                invalid_labels = [label for label, _ in data if not label_pattern.match(label)]
                if invalid_labels:
                    raise ValueError(
                        f"Invalid labels for dense labels: {invalid_labels} (if you want to use "
                        "sparse label, you forgot a parameter `register_length`.)"
                    )

            # Parse ladder operators for special patterns.
            if register_length is not None:
                data = self._flatten_raising_lowering_ops(data, register_length)
            data = self._flatten_ladder_ops(data)

            # set coeffs
            labels, coeffs = zip(*data)
            self._coeffs = np.array(coeffs, dtype=dtype)

            # set labels
            if register_length is None:  # Dense label
                self._register_length = len(labels[0])
                label_pattern = re.compile(r"^[IXYZ]+$")
                invalid_labels = [label for label in labels if not label_pattern.match(label)]
                if invalid_labels:
                    raise ValueError(f"Invalid labels for dense labels are given: {invalid_labels}")
                self._spin_array = np.array(
                    [
                        [[char == "X", char == "Y", char == "Z"] for char in label]
                        for label in labels
                    ],
                    dtype=np.uint8,
                ).transpose((2, 0, 1))
            else:  # Sparse label
                validate_min("register_length", register_length, 1)
                label_pattern = re.compile(r"^[IXYZ]_\d+(\^\d+)?$")
                invalid_labels = [
                    label
                    for label in labels
                    if not all(label_pattern.match(l) for l in label.split())
                ]
                if invalid_labels:
                    raise ValueError(
                        f"Invalid labels for sparse labels are given: {invalid_labels}"
                    )
                self._register_length = register_length
                self._from_sparse_label(labels)

        # Make immutable
        self._spin_array.flags.writeable = False
        self._coeffs.flags.writeable = False
Ejemplo n.º 24
0
    def __init__(
        self,
        atom: Union[str, List[str]] = "H 0.0 0.0 0.0; H 0.0 0.0 0.735",
        unit: UnitsType = UnitsType.ANGSTROM,
        charge: int = 0,
        spin: int = 0,
        basis: str = "sto3g",
        method: MethodType = MethodType.RHF,
        xc_functional: str = "lda,vwn",
        xcf_library: str = "libxc",
        conv_tol: float = 1e-9,
        max_cycle: int = 50,
        init_guess: InitialGuess = InitialGuess.MINAO,
        max_memory: Optional[int] = None,
        chkfile: Optional[str] = None,
    ) -> None:
        """
        Args:
            atom: A string (or a list thereof) denoting the elements and coordinates of all atoms in
                the system. Two formats are allowed; first, the PySCF-style `XYZ` format which is a
                list of strings formatted as `{element symbol} {x_coord} {y_coord} {z_coord}`. If a
                single string is given, the list entries should be joined by `;` as in the example:
                `H 0.0 0.0 0.0; H 0.0 0.0 0.735`.
                Second, the `Z-Matrix` format which is explained at 1_. The previous example
                would be written as `H; H 3 0.735`.
                See also 2_ for more details on geometry specifications supported by PySCF.
            unit: Denotes the unit of coordinates. Valid values are given by the ``UnitsType`` enum.
            charge: The charge of the molecule.
            spin: The spin of the molecule. In accordance with PySCF's definition, the spin equals
                :math:`2*S`, where :math:`S` is the total spin number of the molecule.
            basis: A basis set name as recognized by PySCF (3_), e.g. `sto3g` (the default), `321g`,
                etc. Note, that more advanced configuration options like a Dictionary or custom
                basis sets are not allowed for the moment. Refer to 4_ for an extensive list of
                PySCF's valid basis set names.
            method: The SCF method type to be used for the PySCF calculation. While the name
                refers to HF methods, the PySCFDriver also supports KS methods. Refer to the
                ``MethodType`` for a list of the supported methods.
            xc_functional: One of the predefined Exchange-Correlation functional names as recognized
                by PySCF (5_). Defaults to PySCF's default: 'lda,vwn'. __Note: this setting only has
                an effect when a KS method is chosen for `method`.__
            xcf_library: The Exchange-Correlation functional library to be used. This can be either
                'libxc' (the default) or 'xcfun'. Depending on this value, a different set of values
                for `xc_functional` will be available. Refer to 5_ for more details.
            conv_tol: The SCF convergence tolerance. See 6_ for more details.
            max_cycle: The maximum number of SCF iterations. See 6_ for more details.
            init_guess: The method to make the initial guess for the SCF starting point. Valid
                values are given by the ``InitialGuess`` enum. See 6_ for more details.
            max_memory: The maximum memory that PySCF should use. See 6_ for more details.
            chkfile: The path to a PySCF checkpoint file from which to load a previously run
                calculation. The data stored in this file is assumed to be already converged.
                Refer to 6_ and 7_ for more details.

        Raises:
            QiskitNatureError: An invalid input was supplied.

        .. _1: https://en.wikipedia.org/wiki/Z-matrix_(chemistry)
        .. _2: https://pyscf.org/user/gto.html#geometry
        .. _3: https://pyscf.org/user/gto.html#basis-set
        .. _4: https://pyscf.org/pyscf_api_docs/pyscf.gto.basis.html#module-pyscf.gto.basis
        .. _5: https://pyscf.org/user/dft.html#predefined-xc-functionals-and-functional-aliases
        .. _6: https://pyscf.org/pyscf_api_docs/pyscf.scf.html#module-pyscf.scf.hf
        .. _7: https://pyscf.org/pyscf_api_docs/pyscf.lib.html#module-pyscf.lib.chkfile
        """
        super().__init__()
        # pylint: disable=import-error
        from pyscf import gto, scf

        # First, ensure that PySCF supports the method
        PySCFDriver.check_method_supported(method)

        if isinstance(atom, list):
            atom = ";".join(atom)
        elif isinstance(atom, str):
            atom = atom.replace("\n", ";")
        else:
            raise QiskitNatureError(
                f"`atom` must be either a `str` or `List[str]`, but you passed {atom}"
            )

        validate_min("max_cycle", max_cycle, 1)

        # we use the property-setter to deal with conversion
        self.atom = atom
        self._unit = unit
        self._charge = charge
        self._spin = spin
        self._basis = basis
        self._method = method
        self._xc_functional = xc_functional
        self.xcf_library = xcf_library  # validate choice in property setter
        self._conv_tol = conv_tol
        self._max_cycle = max_cycle
        self._init_guess = init_guess.value
        self._max_memory = max_memory
        self._chkfile = chkfile

        self._mol: gto.Mole = None
        self._calc: scf.HF = None
Ejemplo n.º 25
0
    def __init__(
        self,
        var_form: Optional[QuantumCircuit] = None,
        optimizer: Optional[Optimizer] = None,
        initial_point: Optional[np.ndarray] = None,
        gradient: Optional[Union[GradientBase, Callable]] = None,
        expectation: Optional[ExpectationBase] = None,
        include_custom: bool = False,
        max_evals_grouped: int = 1,
        callback: Optional[Callable[[int, np.ndarray, float, float],
                                    None]] = None,
        quantum_instance: Optional[Union[QuantumInstance, BaseBackend,
                                         Backend]] = None
    ) -> None:
        """

        Args:
            var_form: A parameterized circuit used as Ansatz for the wave function.
            optimizer: A classical optimizer.
            initial_point: An optional initial point (i.e. initial parameter values)
                for the optimizer. If ``None`` then VQE will look to the variational form for a
                preferred point and if not will simply compute a random one.
            gradient: An optional gradient function or operator for optimizer.
            expectation: The Expectation converter for taking the average value of the
                Observable over the var_form state function. When ``None`` (the default) an
                :class:`~qiskit.opflow.expectations.ExpectationFactory` is used to select
                an appropriate expectation based on the operator and backend. When using Aer
                qasm_simulator backend, with paulis, it is however much faster to leverage custom
                Aer function for the computation but, although VQE performs much faster
                with it, the outcome is ideal, with no shot noise, like using a state vector
                simulator. If you are just looking for the quickest performance when choosing Aer
                qasm_simulator and the lack of shot noise is not an issue then set `include_custom`
                parameter here to ``True`` (defaults to ``False``).
            include_custom: When `expectation` parameter here is None setting this to ``True`` will
                allow the factory to include the custom Aer pauli expectation.
            max_evals_grouped: Max number of evaluations performed simultaneously. Signals the
                given optimizer that more than one set of parameters can be supplied so that
                potentially the expectation values can be computed in parallel. Typically this is
                possible when a finite difference gradient is used by the optimizer such that
                multiple points to compute the gradient can be passed and if computed in parallel
                improve overall execution time. Deprecated if a gradient operator or function is
                given.
            callback: a callback that can access the intermediate data during the optimization.
                Four parameter values are passed to the callback as follows during each evaluation
                by the optimizer for its current set of parameters as it works towards the minimum.
                These are: the evaluation count, the optimizer parameters for the
                variational form, the evaluated mean and the evaluated standard deviation.`
            quantum_instance: Quantum Instance or Backend
        """
        validate_min('max_evals_grouped', max_evals_grouped, 1)
        if var_form is None:
            var_form = RealAmplitudes()

        if optimizer is None:
            optimizer = SLSQP()

        # set the initial point to the preferred parameters of the variational form
        if initial_point is None and hasattr(var_form,
                                             'preferred_init_points'):
            initial_point = var_form.preferred_init_points

        self._max_evals_grouped = max_evals_grouped
        self._circuit_sampler = None  # type: Optional[CircuitSampler]
        self._expectation = expectation
        self._user_valid_expectation = self._expectation is not None
        self._include_custom = include_custom
        self._expect_op = None

        super().__init__(var_form=var_form,
                         optimizer=optimizer,
                         cost_fn=self._energy_evaluation,
                         gradient=gradient,
                         initial_point=initial_point,
                         quantum_instance=quantum_instance)
        self._ret = VQEResult()
        self._eval_time = None
        self._optimizer.set_max_evals_grouped(max_evals_grouped)
        self._callback = callback

        self._eval_count = 0
        logger.info(self.print_settings())
 def k(self, k: int) -> None:
     """set k (number of eigenvalues requested)"""
     validate_min("k", k, 1)
     self._k = k
Ejemplo n.º 27
0
 def k(self, k: int) -> None:
     """ set k (number of eigenvalues requested) """
     validate_min('k', k, 1)
     self._in_k = k
     self._check_set_k()
Ejemplo n.º 28
0
    def construct_circuit(self,
                          N: int,
                          a: int = 2,
                          measurement: bool = False) -> QuantumCircuit:
        """Construct circuit.

        Args:
            N: The integer to be factored, has a min. value of 3.
            a: Any integer that satisfies 1 < a < N and gcd(a, N) = 1.
            measurement: Boolean flag to indicate if measurement should be included in the circuit.

        Returns:
            Quantum circuit.

        Raises:
            ValueError: Invalid N
        """
        validate_min('N', N, 3)
        validate_min('a', a, 2)

        # check the input integer
        if N < 1 or N % 2 == 0:
            raise ValueError(
                'The input needs to be an odd integer greater than 1.')

        if a >= N or math.gcd(a, N) != 1:
            raise ValueError(
                'The integer a needs to satisfy a < N and gcd(a, N) = 1.')

        # Get n value used in Shor's algorithm, to know how many qubits are used
        self._n = math.ceil(math.log(N, 2))
        self._qft.num_qubits = self._n + 1
        self._iqft.num_qubits = self._n + 1

        # quantum register where the sequential QFT is performed
        self._up_qreg = QuantumRegister(2 * self._n, name='up')
        # quantum register where the multiplications are made
        self._down_qreg = QuantumRegister(self._n, name='down')
        # auxiliary quantum register used in addition and multiplication
        self._aux_qreg = QuantumRegister(self._n + 2, name='aux')

        # Create Quantum Circuit
        circuit = QuantumCircuit(self._up_qreg,
                                 self._down_qreg,
                                 self._aux_qreg,
                                 name="Shor(N={}, a={})".format(N, a))

        # Create gates to perform addition/subtraction by N in Fourier Space
        self._phi_add_N = self._phi_add_gate(self._aux_qreg.size - 1,
                                             self._get_angles(N))
        self._iphi_add_N = self._phi_add_N.inverse()

        # Create maximal superposition in top register
        circuit.h(self._up_qreg)

        # Initialize down register to 1
        circuit.x(self._down_qreg[0])

        # Apply the multiplication gates as showed in
        # the report in order to create the exponentiation
        for i, ctl_up in enumerate(self._up_qreg):  # type: ignore
            a = int(pow(a, pow(2, i)))
            controlled_multiple_mod_N = self._controlled_multiple_mod_N(
                len(self._down_qreg) + len(self._aux_qreg) + 1,
                N,
                a,
            )
            circuit.append(controlled_multiple_mod_N,
                           [ctl_up, *self._down_qreg, *self._aux_qreg])

        # Apply inverse QFT
        iqft = QFT(len(self._up_qreg)).inverse().to_instruction()
        circuit.append(iqft, self._up_qreg)

        if measurement:
            up_cqreg = ClassicalRegister(2 * self._n, name='m')
            circuit.add_register(up_cqreg)
            circuit.measure(self._up_qreg, up_cqreg)

        logger.info(summarize_circuits(circuit))

        return circuit
Ejemplo n.º 29
0
    def factor(
        self,
        N: int,
        a: int = 2,
    ) -> 'ShorResult':
        """Execute the algorithm.

        The input integer :math:`N` to be factored is expected to be odd and greater than 2.
        Even though this implementation is general, its capability will be limited by the
        capacity of the simulator/hardware. Another input integer :math:`a`  can also be supplied,
        which needs to be a co-prime smaller than :math:`N` .

        Args:
            N: The integer to be factored, has a min. value of 3.
            a: Any integer that satisfies 1 < a < N and gcd(a, N) = 1.

        Returns:
            ShorResult: results of the algorithm.

        Raises:
            ValueError: Invalid input
            AlgorithmError: If a quantum instance or backend has not been provided

        """
        validate_min('N', N, 3)
        validate_min('a', a, 2)

        # check the input integer
        if N < 1 or N % 2 == 0:
            raise ValueError(
                'The input needs to be an odd integer greater than 1.')

        if a >= N or math.gcd(a, N) != 1:
            raise ValueError(
                'The integer a needs to satisfy a < N and gcd(a, N) = 1.')

        if self.quantum_instance is None:
            raise AlgorithmError(
                "A QuantumInstance or Backend "
                "must be supplied to run the quantum algorithm.")

        result = ShorResult()

        # check if the input integer is a power
        tf, b, p = is_power(N, return_decomposition=True)
        if tf:
            logger.info('The input integer is a power: %s=%s^%s.', N, b, p)
            result.factors.append(b)

        if not result.factors:
            logger.debug('Running with N=%s and a=%s.', N, a)

            if self._quantum_instance.is_statevector:
                circuit = self.construct_circuit(N=N, a=a, measurement=False)
                logger.warning('The statevector_simulator might lead to '
                               'subsequent computation using too much memory.')
                result = self._quantum_instance.execute(circuit)
                complete_state_vec = result.get_statevector(circuit)
                # TODO: this uses too much memory
                up_qreg_density_mat = partial_trace(
                    complete_state_vec, range(2 * self._n, 4 * self._n + 2))
                up_qreg_density_mat_diag = np.diag(up_qreg_density_mat)

                counts = dict()
                for i, v in enumerate(up_qreg_density_mat_diag):
                    if not v == 0:
                        counts[bin(int(i))[2:].zfill(2 * self._n)] = v**2
            else:
                circuit = self.construct_circuit(N=N, a=a, measurement=True)
                counts = self._quantum_instance.execute(circuit).get_counts(
                    circuit)

            result.total_counts = len(counts)

            # For each simulation result, print proper info to user
            # and try to calculate the factors of N
            for measurement in list(counts.keys()):
                # Get the x_final value from the final state qubits
                logger.info("------> Analyzing result %s.", measurement)
                factors = self._get_factors(N, a, measurement)

                if factors:
                    logger.info('Found factors %s from measurement %s.',
                                factors, measurement)
                    result.successful_counts = result.successful_counts + 1
                    if factors not in result.factors:
                        result.factors.append(factors)

        return result
Ejemplo n.º 30
0
    def __init__(
        self,
        ansatz: Optional[QuantumCircuit] = None,
        k: int = 2,
        betas: Optional[List[float]] = None,
        optimizer: Optional[Union[Optimizer, Minimizer]] = None,
        initial_point: Optional[np.ndarray] = None,
        gradient: Optional[Union[GradientBase, Callable]] = None,
        expectation: Optional[ExpectationBase] = None,
        include_custom: bool = False,
        max_evals_grouped: int = 1,
        callback: Optional[Callable[[int, np.ndarray, float, float],
                                    None]] = None,
        quantum_instance: Optional[Union[QuantumInstance, Backend]] = None,
    ) -> None:
        """

        Args:
            ansatz: A parameterized circuit used as ansatz for the wave function.
            k: the number of eigenvalues to return. Returns the lowest k eigenvalues.
            betas: beta parameter in the VQD paper. Should have size k -1, the number of excited states.
                It is a hyperparameter that balances the contribution of the overlap
                term to the cost function and has a default value computed as
                mean square sum of coefficients of observable.
            optimizer: A classical optimizer. Can either be a Qiskit optimizer or a callable
                that takes an array as input and returns a Qiskit or SciPy optimization result.
            initial_point: An optional initial point (i.e. initial parameter values)
                for the optimizer. If ``None`` then VQD will look to the ansatz for a preferred
                point and if not will simply compute a random one.
            gradient: An optional gradient function or operator for optimizer.
                Only used to compute the ground state at the moment.
            expectation: The Expectation converter for taking the average value of the
                Observable over the ansatz state function. When ``None`` (the default) an
                :class:`~qiskit.opflow.expectations.ExpectationFactory` is used to select
                an appropriate expectation based on the operator and backend. When using Aer
                qasm_simulator backend, with paulis, it is however much faster to leverage custom
                Aer function for the computation but, although VQD performs much faster
                with it, the outcome is ideal, with no shot noise, like using a state vector
                simulator. If you are just looking for the quickest performance when choosing Aer
                qasm_simulator and the lack of shot noise is not an issue then set `include_custom`
                parameter here to ``True`` (defaults to ``False``).
            include_custom: When `expectation` parameter here is None setting this to ``True`` will
                allow the factory to include the custom Aer pauli expectation.
            max_evals_grouped: Max number of evaluations performed simultaneously. Signals the
                given optimizer that more than one set of parameters can be supplied so that
                multiple points to compute the gradient can be passed and if computed in parallel
                potentially the expectation values can be computed in parallel. Typically this is
                possible when a finite difference gradient is used by the optimizer such that
                improve overall execution time. Deprecated if a gradient operator or function is
                given.
            callback: a callback that can access the intermediate data during the optimization.
                Four parameter values are passed to the callback as follows during each evaluation
                by the optimizer for its current set of parameters as it works towards the minimum.
                These are: the evaluation count, the optimizer parameters for the
                ansatz, the evaluated mean and the evaluated standard deviation.`
            quantum_instance: Quantum Instance or Backend

        """
        validate_min("max_evals_grouped", max_evals_grouped, 1)

        super().__init__()

        self._max_evals_grouped = max_evals_grouped
        self._circuit_sampler = None  # type: Optional[CircuitSampler]
        self._expectation = None
        self.expectation = expectation
        self._include_custom = include_custom

        # set ansatz -- still supporting pre 0.18.0 sorting

        self._ansatz = None
        self.ansatz = ansatz

        self.k = k
        self.betas = betas

        self._optimizer = None
        self.optimizer = optimizer

        self._initial_point = None
        self.initial_point = initial_point
        self._gradient = None
        self.gradient = gradient
        self._quantum_instance = None

        if quantum_instance is not None:
            self.quantum_instance = quantum_instance

        self._eval_time = None
        self._eval_count = 0
        self._callback = None
        self.callback = callback

        logger.info(self.print_settings())