diff --git a/src/orquestra/opt/api/_problem_evaluation.py b/src/orquestra/opt/api/_problem_evaluation.py index 8075f6a..3abb743 100644 --- a/src/orquestra/opt/api/_problem_evaluation.py +++ b/src/orquestra/opt/api/_problem_evaluation.py @@ -25,9 +25,10 @@ def solve_problem_by_exhaustive_search( hamiltonian: cost hamiltonian Returns: - float: value of the best solution - List[Tuple[int]]: list of solutions which correspond to the best value, each - solution is a tuple of ints. + A tuple with the following two elements: + - value of the best solution + - list of solutions which correspond to the best value, each solution is a + tuple of ints. """ cost_function = _evaluate_solution_for_hamiltonian @@ -50,12 +51,13 @@ def solve_graph_problem_by_exhaustive_search( Args: graph: graph for which we want to solve the problem cost_function: function which calculates the cost of solution of a given - problem. + problem. Returns: - float: value of the best solution - List[Tuple[int]]: list of solutions which correspond to the best value, each - solution is a tuple of ints. + A tuple with the following two elements: + - value of the best solution + - list of solutions which correspond to the best value, each solution is a + tuple of ints. """ num_nodes = graph.number_of_nodes() return _solve_bitstring_problem_by_exhaustive_search( @@ -79,9 +81,10 @@ def _solve_bitstring_problem_by_exhaustive_search( num_nodes: number of nodes of the graph for which we want to solve the problem Returns: - float: value of the best solution - List[Tuple[int]]: list of solutions which correspond to the best value, each - solution is a tuple of ints. + A tuple with the following two elements: + - value of the best solution + - list of solutions which correspond to the best value, each solution is a + tuple of ints. """ solutions_list = [] @@ -110,7 +113,7 @@ def evaluate_solution( solution: solution to a problem as a tuple of bits graph: a graph for which we want to solve the problem get_hamiltonian: function which translates graph into a Hamiltonian representing - a problem. + a problem. Returns: float: value of a solution. diff --git a/src/orquestra/opt/api/optimizer.py b/src/orquestra/opt/api/optimizer.py index b8c33f7..c7f4cf2 100644 --- a/src/orquestra/opt/api/optimizer.py +++ b/src/orquestra/opt/api/optimizer.py @@ -16,8 +16,7 @@ SimpleRecorderWithGradient, ) from ..history.recorder import recorder as _recorder -from . import CallableWithGradient, CostFunction -from .cost_function import _CostFunction +from .cost_function import CallableWithGradient, CostFunction class Optimizer(ABC): @@ -47,8 +46,6 @@ def minimize( evaluations should be recorded. """ cost_function = self._preprocess_cost_function(cost_function) - x: _CostFunction = self.recorder(cost_function) - print(x) if keep_history: cost_function = self.recorder(cost_function) return self._minimize(cost_function, initial_params, keep_history) @@ -151,15 +148,15 @@ class NestedOptimizer(ABC): Returns: An instance of OptimizeResult containing: - opt_value, - opt_params, - nit: total number of iterations of inner_optimizer, - nfev: total number of calls to cost function, - history: a list of HistoryEntrys. - If keep_history is False this should be an empty list. - gradient_history: if the cost function is a FunctionWithGradient, - this should be a list of HistoryEntrys representing - previous calls to the gradient. + - opt_value: optimal value of the objective function + - opt_params: corresponding optimal parameters + - nit: total number of iterations of inner_optimizer, + - nfev: total number of calls to cost function, + - history: a list of HistoryEntrys. + If keep_history is False this should be an empty list. + - gradient_history: if the cost function is a FunctionWithGradient, + this should be a list of HistoryEntrys representing + previous calls to the gradient. """ @property diff --git a/src/orquestra/opt/api/optimizer_test.py b/src/orquestra/opt/api/optimizer_test.py index 4e52da3..83a9664 100644 --- a/src/orquestra/opt/api/optimizer_test.py +++ b/src/orquestra/opt/api/optimizer_test.py @@ -216,14 +216,17 @@ def _validate_changing_keep_history_does_not_change_results( other projects. Usage: - from orquestra.opt.api.optimizer_test import NESTED_OPTIMIZER_CONTRACTS - - @pytest.mark.parametrize("contract", NESTED_OPTIMIZER_CONTRACTS) - def test_nestedoptimizer_contract(contract): - optimizer = MockNestedOptimizer(inner_optimizer=MockOptimizer(), n_iters=5) - cost_function_factory = ... - initial_params = ... - assert contract(optimizer, cost_function_factory, initial_params) + + .. code:: python + + from orquestra.opt.api.optimizer_test import NESTED_OPTIMIZER_CONTRACTS + + @pytest.mark.parametrize("contract", NESTED_OPTIMIZER_CONTRACTS) + def test_nestedoptimizer_contract(contract): + optimizer = MockNestedOptimizer(inner_optimizer=MockOptimizer(), n_iters=5) + cost_function_factory = ... + initial_params = ... + assert contract(optimizer, cost_function_factory, initial_params) """ diff --git a/src/orquestra/opt/bqm/conversions.py b/src/orquestra/opt/bqm/conversions.py index 8a13c09..022f150 100644 --- a/src/orquestra/opt/bqm/conversions.py +++ b/src/orquestra/opt/bqm/conversions.py @@ -24,7 +24,7 @@ def convert_qubo_to_paulisum(qubo: BinaryQuadraticModel) -> PauliSum: qubo: Object we want to convert Returns: - PauliSum: PauliSum representation of the input qubo. + PauliSum representation of the input qubo. """ linear_coeffs, quadratic_coeffs, offset = qubo.to_ising() diff --git a/src/orquestra/opt/cost_function_augmentations.py b/src/orquestra/opt/cost_function_augmentations.py index fa61b94..d3ee6bd 100644 --- a/src/orquestra/opt/cost_function_augmentations.py +++ b/src/orquestra/opt/cost_function_augmentations.py @@ -9,16 +9,20 @@ Cost functions are augmented via `augment_cost_function`. Basic usage looks as follows -augmented_func = augment_cost_function(func, [function_logger(level=level)]) +.. code:: python + + augmented_func = augment_cost_function(func, [function_logger(level=level)]) If the function to be augmented has gradient, separate augmentations can be applied to the function and the gradient, e.g.: -augmented_func = augment_cost_function( - func, - cost_function_augmentations=[function_logger(level=logging.INFO)], - gradient_augmentations=[function_logger(level=logging.DEBUG)] -) +.. code:: python + + augmented_func = augment_cost_function( + func, + cost_function_augmentations=[function_logger(level=logging.INFO)], + gradient_augmentations=[function_logger(level=logging.DEBUG)] + ) In principle, any function mapping cost function to cost function can be used as diff --git a/src/orquestra/opt/history/recorder.py b/src/orquestra/opt/history/recorder.py index a67e27f..b296332 100644 --- a/src/orquestra/opt/history/recorder.py +++ b/src/orquestra/opt/history/recorder.py @@ -373,8 +373,10 @@ def recorder(function, save_condition: SaveCondition = always): The return type depends on the passed callable. See overloads defined above to check for available variants. Here is a summary: - recorder is always callable + - if `function` has gradient, so does the recorder. Calls to gradient and calls made by gradient are NOT recorded. + - if `function` has possibility to store artifacts (i.e. accepts `store_artifact` argument, then so does the recorder. """ diff --git a/src/orquestra/opt/problems/graph.py b/src/orquestra/opt/problems/graph.py index 5f93334..6ad525b 100644 --- a/src/orquestra/opt/problems/graph.py +++ b/src/orquestra/opt/problems/graph.py @@ -69,11 +69,12 @@ def generate_random_graph_erdos_renyi( connecting nodes randomly. Each edge is included in the graph with probability p independent from every other edge. Equivalently, all graphs with n nodes and M edges have equal probability. + Args: num_nodes: Number of nodes in the result graph. edge_probability: Probability of connecting two nodes. weight_sampler: Used to sample edge weights. Defaults `static_sampler`, - i.e. all edge weights are set to 1.0. + i.e. all edge weights are set to 1.0. seed: if provided, sets the global seed """ output_graph = nx.erdos_renyi_graph(n=num_nodes, p=edge_probability, seed=seed) @@ -91,11 +92,12 @@ def generate_random_regular_graph( """Randomly generate a d-regular graph. A graph is generated by picking uniformly a graph among the set of graphs with the desired number of nodes and degree. + Args: num_nodes: Number of nodes in the generated graph. degree: Degree of each edge. weight_sampler: Used to sample edge weights. Defaults `static_sampler`, - i.e. all edge weights are set to 1.0. + i.e. all edge weights are set to 1.0. seed: if provided, sets the global seed """ output_graph = nx.random_regular_graph(d=degree, n=num_nodes, seed=seed) diff --git a/tests/orquestra/opt/history/recording_functions_test.py b/tests/orquestra/opt/history/recording_functions_test.py index dc3deca..d4a200a 100644 --- a/tests/orquestra/opt/history/recording_functions_test.py +++ b/tests/orquestra/opt/history/recording_functions_test.py @@ -123,8 +123,11 @@ def test_recorder_records_only_calls_for_which_save_condition_evaluates_to_true( assert [entry.call_number for entry in function.history] == list( expected__call_numbers ) - np.testing.assert_array_equal( - [entry.params for entry in function.history], list(expected_params) + assert all( + np.array_equal(arr1, arr2) + for arr1, arr2 in zip( + [entry.params for entry in function.history], expected_params + ) ) assert [entry.value for entry in function.history] == list(expected_values)