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
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()
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
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()
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
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
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
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
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
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
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}.' )
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)
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)
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.")
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
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
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]
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
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)
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
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, )
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
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
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
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()
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
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
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())