def minimize(
        self, cost_function: CallableWithGradient, initial_params: np.ndarray
    ) -> OptimizeResult:
        """Minimize using the Covariance Matrix Adaptation Evolution Strategy
        (CMA-ES).

        Args:
            cost_function: object representing cost function we want to minimize
            initial_params: initial guess for the ansatz parameters.

        Returns:
            tuple: A tuple containing an optimization results dict and a numpy array
                with the optimized parameters.
        """

        # Optimization Results Object
        cost_function = recorder(cost_function)

        strategy = cma.CMAEvolutionStrategy(initial_params, self.sigma_0, self.options)
        result = strategy.optimize(cost_function).result

        return optimization_result(
            opt_value=result.fbest,
            opt_params=result.xbest,
            history=cost_function.history,
            nfev=result.evaluations,
            nit=result.iterations,
            cma_xfavorite=list(result.xfavorite),
        )
Exemple #2
0
def test_recorder_can_be_copied_deeply(func):
    recorded = recorder(func)

    recorded_copy = deepcopy(recorded)

    assert recorded_copy.target == recorded.target
    assert recorded_copy.predicate == recorded.predicate
Exemple #3
0
def test_recorder_can_be_copied_shallowly(func):
    recorded = recorder(func)

    recorded_copy = copy(recorded)

    assert recorded_copy.target is recorded.target
    assert recorded_copy.predicate is recorded.predicate
    def test_evaluate_history(self):
        for distance_meas, distance_measure_params in param_list:
            with self.subTest():
                # Given
                self.distance_measure = distance_meas
                distance_measure_parameters = distance_measure_params

                cost_function = QCBMCostFunction(
                    self.ansatz,
                    self.backend,
                    self.distance_measure,
                    distance_measure_parameters,
                    self.target_bitstring_distribution,
                )

                cost_function = recorder(cost_function)

                params = np.array([0, 0, 0, 0])

                # When
                value_estimate = cost_function(params)
                history = cost_function.history

                # Then
                self.assertEqual(len(history), 1)
                self.assertEqual(
                    BitstringDistribution,
                    type(history[0].artifacts["bitstring_distribution"]),
                )
                np.testing.assert_array_equal(params, history[0].params)
                self.assertEqual(value_estimate, history[0].value)
def test_recorder_correctly_sets_attributes_of_recorder_function(func):
    func.custom_attribute = "custom-attr"

    recorded = recorder(func)

    recorded.custom_attribute = "new-value"

    assert func.custom_attribute == "new-value"
Exemple #6
0
def test_recorder_stores_all_artifacts_by_default(
    source_function: CallableStoringArtifacts, params_sequence, expected_artifacts
):
    function = recorder(source_function)
    for param in params_sequence:
        function(param)

    assert [entry.artifacts for entry in function.history] == expected_artifacts
Exemple #7
0
def test_recorder_does_not_make_any_redundant_calls_to_wrapped_function(
        source_function, params_sequence):
    spy = Mock(wraps=source_function)
    function = recorder(spy)

    for params in params_sequence:
        function(params)

    assert spy.call_args_list == [call(params) for params in params_sequence]
Exemple #8
0
    def test_history_is_empty_if_keep_value_history_is_false(self):
        cost_function = recorder(sum_x_squared)

        cost_function(np.array([1, 2, 3]))

        history_info = construct_history_info(cost_function, False)

        assert not history_info["history"]
        assert "gradient_history" not in history_info
def test_recorder_correctly_gets_attributes_of_recorder_function(func):
    func.custom_attribute = "custom-attr"

    recorded = recorder(func)

    assert recorded.custom_attribute == func.custom_attribute

    func.custom_attribute = "some-other-value"

    assert recorded.custom_attribute == func.custom_attribute
Exemple #10
0
def test_calls_to_gradient_are_also_recorded(function: CallableWithGradient,
                                             params: np.ndarray):
    target = recorder(function)
    np.testing.assert_array_equal(function.gradient(params),
                                  target.gradient(params))

    assert len(target.gradient.history) == 1
    entry = target.gradient.history[0]

    assert entry.call_number == 0
    np.testing.assert_array_equal(entry.params, params)
    np.testing.assert_array_equal(entry.value, target.gradient(params))
Exemple #11
0
def test_by_default_recorder_records_all_evaluations(source_function,
                                                     params_sequence):
    function = recorder(source_function)

    for params in params_sequence:
        function(params)

    assert [entry.params for entry in function.history] == params_sequence
    assert [entry.value for entry in function.history
            ] == [source_function(params) for params in params_sequence]
    assert [entry.call_number
            for entry in function.history] == list(range(len(params_sequence)))
Exemple #12
0
    def minimize(self, cost_function, initial_params=None):
        """
        Minimizes given cost function using optimizers from Qiskit Aqua.

        Args:
            cost_function(): python method which takes numpy.ndarray as input
            initial_params(np.ndarray): initial parameters to be used for optimization

        Returns:
            optimization_results(scipy.optimize.OptimizeResults): results of the optimization.
        """
        history = []

        if self.method == "SPSA":
            optimizer = SPSA(**self.options)
        elif self.method == "ADAM" or self.method == "AMSGRAD":
            if self.method == "AMSGRAD":
                self.options["amsgrad"] = True
            optimizer = ADAM(**self.options)

        number_of_variables = len(initial_params)

        if self.keep_value_history:
            cost_function_wrapper = recorder(cost_function)
        else:
            cost_function_wrapper = _CostFunctionWrapper(cost_function)

        gradient_function = None
        if hasattr(cost_function, "gradient") and callable(
                getattr(cost_function, "gradient")):
            gradient_function = cost_function.gradient

        solution, value, nit = optimizer.optimize(
            num_vars=number_of_variables,
            objective_function=cost_function_wrapper,
            initial_point=initial_params,
            gradient_function=gradient_function,
        )

        if self.keep_value_history:
            nfev = len(cost_function_wrapper.history)
            history = cost_function_wrapper.history
        else:
            nfev = cost_function_wrapper.number_of_calls
            history = []

        return optimization_result(
            opt_value=value,
            opt_params=solution,
            nit=nit,
            history=history,
            nfev=nfev,
        )
Exemple #13
0
def test_recorder_stores_history_entry_if_artifact_is_force_stored():
    function = recorder(function_4, save_condition=every_nth(5))
    for n in [0, 2, 3, 5, 7, 5]:
        function(n)

    assert [entry.call_number for entry in function.history] == [0, 1, 5]
    assert [entry.value for entry in function.history] == [0, 4, 10]
    assert [entry.params for entry in function.history] == [0, 2, 5]
    assert [entry.artifacts for entry in function.history] == [
        {"bitstring": "0"},
        {"bitstring": "10"},
        {"bitstring": "101"},
    ]
Exemple #14
0
    def test_optimizer_records_history_if_keep_value_history_is_added_as_option(self):
        optimizer = QiskitOptimizer(
            method="SPSA",
            options={"keep_value_history": True}
        )

        # To check that history is recorded correctly, we wrap cost_function
        # with a recorder. Optimizer should wrap it a second time and
        # therefore we can compare two histories to see if they agree.
        cost_function = recorder(sum_x_squared)

        result = optimizer.minimize(cost_function, np.array([-1, 1]))

        self.assertEqual(result.history, cost_function.history)
Exemple #15
0
    def test_history_info_contains_only_history_for_function_without_gradient(
            self):
        cost_function = recorder(sum_x_squared)

        cost_function(np.array([1, 2, 3]))

        history_info = construct_history_info(cost_function, True)

        assert len(history_info["history"]) == 1
        assert "gradient_history" not in history_info

        history_entry = history_info["history"][0]
        assert history_entry.call_number == 0
        np.testing.assert_array_equal(history_entry.params, [1, 2, 3])
        assert history_entry.value == cost_function(np.array([1, 2, 3]))
Exemple #16
0
def test_recorder_records_only_calls_for_which_save_condition_evaluates_to_true(
        source_function, params_sequence, condition: SaveCondition):
    function = recorder(source_function, save_condition=condition)
    expected_values, expected_params, expected__call_numbers = zip(*filter(
        lambda x: condition(*x),
        ((source_function(params), params, i)
         for i, params in enumerate(params_sequence)),
    ))
    for params in params_sequence:
        function(params)

    assert [entry.call_number
            for entry in function.history] == list(expected__call_numbers)
    assert [entry.params
            for entry in function.history] == list(expected_params)
    assert [entry.value for entry in function.history] == list(expected_values)
Exemple #17
0
    def minimize(self, cost_function, initial_params=None, callback=None):
        """
        Minimizes given cost function using functions from scipy.minimize.

        Args:
            cost_function(): python method which takes numpy.ndarray as input
            initial_params(np.ndarray): initial parameters to be used for optimization
            callback(): callback function. If none is provided, a default one will be used.

        Returns:
            optimization_results(scipy.optimize.OptimizeResults): results of the optimization.
        """

        if self.keep_value_history:
            cost_function = recorder(cost_function)

        jacobian = None
        if hasattr(cost_function, "gradient") and callable(
                getattr(cost_function, "gradient")):
            jacobian = cost_function.gradient

        result = scipy.optimize.minimize(
            cost_function,
            initial_params,
            method=self.method,
            options=self.options,
            constraints=self.constraints,
            jac=jacobian,
        )
        opt_value = result.fun
        opt_params = result.x

        nit = result.get("nit", None)
        nfev = result.get("nfev", None)

        return optimization_result(
            opt_value=opt_value,
            opt_params=opt_params,
            nit=nit,
            nfev=nfev,
            history=cost_function.history if self.keep_value_history else [],
        )
    def test_evaluate_history(self, cost_function_factory, distance_measure_kwargs):
        # Given
        cost_function = cost_function_factory(
            ansatz,
            backend,
            n_samples,
            **distance_measure_kwargs,
            target_bitstring_distribution=target_bitstring_distribution,
        )

        cost_function = recorder(cost_function)

        params = np.array([0, 0, 0, 0])

        # When
        value_estimate = cost_function(params)
        history = cost_function.history

        # Then
        assert len(history) == 1
        np.testing.assert_array_equal(params, history[0].params)
        assert value_estimate == history[0].value
Exemple #19
0
    def minimize(
            self,
            cost_function: CallableWithGradient,
            initial_params: Optional[np.ndarray] = None) -> OptimizeResult:
        """
        Finds the parameters which minimize given cost function, by trying all the parameters from the grid.

        Args:
            cost_function(zquantum.core.interfaces.cost_function.CostFunction): object representing cost function we want to minimize
            inital_params (np.ndarray): initial parameters for the cost function

        Returns:
            OptimizeResults
        """
        if initial_params is not None and len(initial_params) != 0:
            Warning(
                "Grid search doesn't use initial parameters, they will be ignored."
            )
        history = []
        min_value = None
        nfev = 0

        if self.keep_value_history:
            cost_function = recorder(cost_function)

        for params in self.grid.params_list:
            value = cost_function(params)
            nfev += 1
            if min_value is None or value < min_value:
                min_value = value
                optimal_params = params

        return optimization_result(
            opt_value=min_value,
            opt_params=optimal_params,
            nfev=nfev,
            nit=None,
            history=cost_function.history if self.keep_value_history else [])
Exemple #20
0
    def test_history_info_contains_gradient_history_for_function_with_gradient(
            self):
        cost_function = recorder(
            FunctionWithGradient(sum_x_squared,
                                 finite_differences_gradient(sum_x_squared)))

        cost_function(np.array([1, 2, 3]))
        cost_function.gradient(np.array([0, -1, 1]))

        history_info = construct_history_info(cost_function, True)

        assert len(history_info["history"]) == 1
        assert len(history_info["gradient_history"]) == 1

        history_entry = history_info["history"][0]
        assert history_entry.call_number == 0
        np.testing.assert_array_equal(history_entry.params, [1, 2, 3])
        assert history_entry.value == cost_function(np.array([1, 2, 3]))

        history_entry = history_info["gradient_history"][0]
        assert history_entry.call_number == 0
        np.testing.assert_array_equal(history_entry.params, [0, -1, 1])
        np.testing.assert_array_equal(
            history_entry.value, cost_function.gradient(np.array([0, -1, 1])))
def test_recorder_propagates_calls_to_wrapped_functions_and_its_gradient(
        function: CallableWithGradient, params: np.ndarray):
    target = recorder(function)
    assert target(params) == function(params)
    np.testing.assert_array_almost_equal(target.gradient(params),
                                         function.gradient(params))
Exemple #22
0
def test_recorder_propagates_calls_to_wrapped_function(source_function, param):
    function = recorder(source_function)
    assert function(param) == source_function(param)