diff --git a/CHANGELOG.md b/CHANGELOG.md index 67b3fd8..406e37b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ Current version: 0.2.0 ### Added - Added tournament selection as an alternative selection method for EVQE ([Issue #25]) +- Add the ability to initialize EVQE individuals with more than one circuit layer ([Issue #26]) ### Fixed @@ -24,5 +25,6 @@ Current version: 0.2.0 - Initial codeless pypi commit +[Issue #26]: https://github.com/DLR-RB/QUEASARS/issues/26 [Issue #25]: https://github.com/DLR-RB/QUEASARS/issues/25 [Issue #23]: https://github.com/DLR-RB/QUEASARS/issues/23 \ No newline at end of file diff --git a/queasars/minimum_eigensolvers/evqe/evqe.py b/queasars/minimum_eigensolvers/evqe/evqe.py index a184d30..3249892 100644 --- a/queasars/minimum_eigensolvers/evqe/evqe.py +++ b/queasars/minimum_eigensolvers/evqe/evqe.py @@ -87,6 +87,11 @@ class EVQEMinimumEigensolverConfiguration: a python ThreadPool executor. If a dask Client is used, both the Sampler and Estimator need to be serializable by dask, otherwise the computation will fail. If no parallel_executor is provided a ThreadPoolExecutor with as many threads as population_size will be launched + :param n_initial_layers: number of layers with which the individuals in the initial population are initialized. + By default, this is set to 1. This should only be increased, if randomize_initial_population_parameters + is set to True, or the parameter_search_probability is high. Otherwise, the added layers may start as an + identity operator and only seldom be optimized, minimizing their effect. + :type n_initial_layers: int :param use_tournament_selection: indicates whether to use tournament selection. By default, this is set to False. In that case, roulette wheel selection is used. Should be true, if the measured expectation values can be negative. @@ -124,6 +129,7 @@ class EVQEMinimumEigensolverConfiguration: parameter_search_probability: float topological_search_probability: float layer_removal_probability: float + n_initial_layers: int = 1 use_tournament_selection: bool = False tournament_size: Optional[int] = None randomize_initial_population_parameters: bool = True @@ -142,6 +148,11 @@ def __post_init__(self): raise ValueError("The topological_search_probability must not exceed the range (0, 1)!") if not 0 <= self.layer_removal_probability <= 1: raise ValueError("The layer_removal_probability must not exceed the range (0, 1)!") + if self.n_initial_layers < 1: + raise ValueError( + "The number of initial layers for each individual " + + f"of the population must be at least 1! But it was {self.n_initial_layers}!" + ) if self.use_tournament_selection and self.tournament_size is None: raise ValueError("To use tournament_selection, a tournament_size must be specified! It cannot be None!") if self.use_tournament_selection and not 1 <= self.tournament_size: @@ -165,7 +176,7 @@ def __init__(self, configuration: EVQEMinimumEigensolverConfiguration): population_initializer: Callable[[int], EVQEPopulation] = lambda n_qubits: EVQEPopulation.random_population( n_qubits=n_qubits, - n_layers=1, + n_layers=configuration.n_initial_layers, n_individuals=configuration.population_size, randomize_parameter_values=configuration.randomize_initial_population_parameters, random_seed=new_random_seed(random_generator=self.random_generator),