From 274015f4eea1c4c9a74ab594fb9a28887d53f961 Mon Sep 17 00:00:00 2001 From: Pietro Berkes Date: Tue, 6 Jun 2023 10:04:51 +0200 Subject: [PATCH 1/4] Fix error in long decription --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 28c8a01..01e7f0e 100755 --- a/README.rst +++ b/README.rst @@ -151,7 +151,7 @@ dynamic programming and is linear O(n): Linear: time = -1.8E-06 + 7.3E-06*n (sec) Report Generation -------- +----------------- This feature allows users to generate a report based on the outputs received from calling the :code:`big-o` function. From 0f2f0dd049bc510ebf64c1242932c4876ce08afc Mon Sep 17 00:00:00 2001 From: Pietro Berkes Date: Fri, 21 Jul 2023 11:09:02 +0200 Subject: [PATCH 2/4] Lint and remove old `import __future__` statements --- big_o/__init__.py | 6 +----- big_o/big_o.py | 2 -- big_o/complexities.py | 1 + big_o/datagen.py | 2 +- big_o/reports.py | 1 + big_o/test/test_big_o.py | 31 +++++++++++++++++-------------- big_o/test/test_complexities.py | 27 ++++++++++++++++----------- big_o/test/test_reports.py | 6 ++++-- 8 files changed, 41 insertions(+), 35 deletions(-) diff --git a/big_o/__init__.py b/big_o/__init__.py index 9d23f71..3e7ed86 100755 --- a/big_o/__init__.py +++ b/big_o/__init__.py @@ -1,10 +1,6 @@ -from __future__ import absolute_import - +from big_o import complexities, datagen, reports # noqa from big_o.big_o import ( # noqa big_o, infer_big_o_class, measure_execution_time, ) -from big_o import reports # noqa -from big_o import complexities # noqa -from big_o import datagen # noqa diff --git a/big_o/big_o.py b/big_o/big_o.py index b715b46..85fa082 100755 --- a/big_o/big_o.py +++ b/big_o/big_o.py @@ -1,5 +1,3 @@ -from __future__ import absolute_import - from timeit import Timer import numpy as np diff --git a/big_o/complexities.py b/big_o/complexities.py index f76e462..e1cbb56 100755 --- a/big_o/complexities.py +++ b/big_o/complexities.py @@ -130,6 +130,7 @@ def __eq__(self, other): def __hash__(self): return id(self) + # --- Concrete implementations of the most popular complexity classes diff --git a/big_o/datagen.py b/big_o/datagen.py index 1551308..9acbf0a 100755 --- a/big_o/datagen.py +++ b/big_o/datagen.py @@ -11,7 +11,7 @@ def n_(n): def range_n(n, start=0): """ Return the sequence [start, start+1, ..., start+N-1]. """ - return list(range(start, start+n)) + return list(range(start, start + n)) def integers(n, min_, max_): diff --git a/big_o/reports.py b/big_o/reports.py index e90af9e..7c9ea97 100644 --- a/big_o/reports.py +++ b/big_o/reports.py @@ -1,5 +1,6 @@ from big_o.complexities import ComplexityClass + def big_o_report(best, others): """ Creates a human-readable report of the output of the big_o function. diff --git a/big_o/test/test_big_o.py b/big_o/test/test_big_o.py index ff8f66c..3ae26f6 100755 --- a/big_o/test/test_big_o.py +++ b/big_o/test/test_big_o.py @@ -1,11 +1,11 @@ -import unittest import time +import unittest + import numpy as np -from numpy.testing import assert_array_equal, assert_array_almost_equal +from numpy.testing import assert_array_almost_equal, assert_array_equal import big_o -from big_o import datagen -from big_o import complexities as compl +from big_o import complexities as compl, datagen def dummy_constant_function(n): @@ -64,12 +64,13 @@ def test_measure_execution_time(self): def f(n): time.sleep(0.1 * n) return n + ns, t = big_o.measure_execution_time( f, datagen.n_, min_n=1, max_n=5, n_measures=5, n_repeats=1, n_timings=5 ) assert_array_equal(ns, np.arange(1, 6)) - assert_array_almost_equal(t*10., np.arange(1, 6), 1) + assert_array_almost_equal(t * 10., np.arange(1, 6), 1) def test_infer_big_o(self): x = np.linspace(10, 100, 100) @@ -94,7 +95,7 @@ def test_infer_big_o(self): def test_infer_big_o_list_input(self): # Check a normal list / iterable can be passed to infer_big_o_class() ns = range(10, 100, 10) - time = [x**2 for x in ns] + time = [x ** 2 for x in ns] best, fitted = big_o.infer_big_o_class(ns, time) @@ -104,8 +105,8 @@ def test_infer_big_o_list_input(self): best_check, fitted_check = big_o.infer_big_o_class(ns_np, time_np) self.assertEqual(best.order, best_check.order, - msg = "Order of complexity {} did not match check complexity {}".format( - best, best_check)) + msg="Order of complexity {} did not match check complexity {}".format( + best, best_check)) self.assertAlmostEqual(fitted[best], fitted_check[best_check]) def test_big_o(self): @@ -120,7 +121,7 @@ def test_big_o(self): (dummy_constant_function, compl.Constant, (1000, 10000)), (dummy_linear_function, compl.Linear, (100, 5000)), (dummy_quadratic_function, compl.Quadratic, (1, 100)), - (dummy_linearithmic_function, compl.Linearithmic, (10, 5000)), + (dummy_linearithmic_function, compl.Linearithmic, (10, 50000)), ] for func, class_, n_range in desired: res_class, fitted = big_o.big_o( @@ -130,7 +131,7 @@ def test_big_o(self): n_measures=25, n_repeats=1, n_timings=10, - return_raw_data = True) + return_raw_data=True) residuals = fitted[res_class] @@ -151,9 +152,11 @@ def test_big_o(self): (complexity, residuals) for complexity, residuals in fitted.items() if isinstance(complexity, class_)) - self.assertIsInstance(res_class, class_, - msg = "Best matched complexity is {} (r={:f}) when {} (r={:f}) was expected" - .format(res_class, residuals, sol_class, sol_residuals)) + self.assertIsInstance( + res_class, class_, + msg="Best matched complexity is {} (r={:f}) when {} (r={:f}) was expected" + .format(res_class, residuals, sol_class, sol_residuals) + ) def test_big_o_return_raw_data_default(self): _, fitted = big_o.big_o( @@ -202,7 +205,7 @@ def dummy(n): measures = fitted['measures'] self.assertEqual(len(measures), n_measures) for i in range(1, n_measures): - self.assertGreater(measures[i], measures[i-1]) + self.assertGreater(measures[i], measures[i - 1]) self.assertIn('times', fitted) times = fitted['times'] diff --git a/big_o/test/test_complexities.py b/big_o/test/test_complexities.py index 9200074..5ca20f9 100644 --- a/big_o/test/test_complexities.py +++ b/big_o/test/test_complexities.py @@ -1,4 +1,5 @@ import unittest + import numpy as np from numpy.testing import assert_allclose @@ -27,13 +28,13 @@ def test_compute(self): ref_y = complexity.compute(x) assert_allclose(y, ref_y, - err_msg = "compute() failed to match expected values for class %r" % class_) + err_msg="compute() failed to match expected values for class %r" % class_) # Check residuals are correct # Use the atol constant from np.allclose() because the default for # np.testing.assert_allclose() for atol (0) is too low for this comparison assert_allclose(residuals, np.sum((y - ref_y) ** 2), rtol=1e-07, atol=1e-08, - err_msg = "fit() residuals failed to match expected value for class %r" % class_) + err_msg="fit() residuals failed to match expected value for class %r" % class_) def test_not_fitted(self): for class_ in complexities.ALL_CLASSES: @@ -65,7 +66,7 @@ def test_fit_residuals(self): for f, class_ in desired: # Adding random noise so the residual doesn't approximate zero y = f(counts + np.abs(rng.standard_normal(counts.size)) * .1) \ - + np.abs(rng.standard_normal(counts.size)) + + np.abs(rng.standard_normal(counts.size)) complexity = class_() residuals = complexity.fit(counts, y) @@ -75,12 +76,12 @@ def test_fit_residuals(self): # Use the atol constant from np.allclose() because the default for # np.testing.assert_allclose() for atol (0) is too low for this comparison assert_allclose(residuals, np.sum((y - ref_y) ** 2), rtol=1e-07, atol=1e-08, - err_msg = "fit() residuals failed to match expected value for class %r" % class_) + err_msg="fit() residuals failed to match expected value for class %r" % class_) def test_fit_list_input(self): # Check a normal list / iterable can be passed to fit() ns = range(10, 100, 10) - time = [x**2 for x in ns] + time = [x ** 2 for x in ns] quadratic = complexities.Quadratic() quadratic.fit(ns, time) @@ -97,9 +98,13 @@ def test_fit_list_input(self): coeff_check = quadratic_check.coeff coefficients_check = quadratic_check.coefficients() - assert_allclose(coeff, coeff_check, - err_msg = "coeff of {} did not match coeff of check complexity {}".format( - quadratic, quadratic_check)) - assert_allclose(coefficients, coefficients_check, - err_msg = "coefficients of {} did not match coefficients of check complexity {}".format( - quadratic, quadratic_check)) + assert_allclose( + coeff, coeff_check, + err_msg="coeff of {} did not match coeff of check complexity {}".format( + quadratic, quadratic_check) + ) + assert_allclose( + coefficients, coefficients_check, + err_msg="coefficients of {} did not match coefficients of check complexity {}".format( + quadratic, quadratic_check) + ) diff --git a/big_o/test/test_reports.py b/big_o/test/test_reports.py index e99666b..82ba34e 100644 --- a/big_o/test/test_reports.py +++ b/big_o/test/test_reports.py @@ -1,7 +1,9 @@ import unittest + import big_o from big_o import reports + class TestReport(unittest.TestCase): def test_report_return(self): @@ -10,9 +12,9 @@ def test_report_return(self): assert isinstance(reports.big_o_report(best, others), str) def test_report_return_raw_data_true(self): - best, others = big_o.big_o(sorted, lambda n: big_o.datagen.integers(n, 100, 500), return_raw_data=True) + best, others = big_o.big_o(sorted, lambda n: big_o.datagen.integers(n, 100, 500), + return_raw_data=True) report = reports.big_o_report(best, others) assert 'measures' not in report assert 'times' not in report - From 72871015e8f3ca6eacd6d84a207c4ffc9b7e46b9 Mon Sep 17 00:00:00 2001 From: Pietro Berkes Date: Fri, 21 Jul 2023 11:11:18 +0200 Subject: [PATCH 3/4] Remove unused code --- big_o/test/test_big_o.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/big_o/test/test_big_o.py b/big_o/test/test_big_o.py index 3ae26f6..afcce3b 100755 --- a/big_o/test/test_big_o.py +++ b/big_o/test/test_big_o.py @@ -73,8 +73,6 @@ def f(n): assert_array_almost_equal(t * 10., np.arange(1, 6), 1) def test_infer_big_o(self): - x = np.linspace(10, 100, 100) - desired = [ (lambda x: x*0.+2., compl.Constant, [2.]), (lambda x: 4.*x, compl.Linear, [0., 4.]), @@ -86,6 +84,7 @@ def test_infer_big_o(self): (lambda x: 0.6**x, compl.Exponential, [0., np.log(0.6)]), ] + x = np.linspace(10, 100, 100) for f, class_, coeff in desired: y = f(x) res_class, fitted = big_o.infer_big_o_class(x, y) @@ -110,11 +109,6 @@ def test_infer_big_o_list_input(self): self.assertAlmostEqual(fitted[best], fitted_check[best_check]) def test_big_o(self): - # Numpy sorts are fast enough that they are very close to linear - # In testing, heapsort was found to follow the best clear n * log(n) curve - random_state = np.random.RandomState() - random_array = random_state.rand(100000) - # Each test case is a tuple # (function_to_evaluate, expected_complexity_class, range_for_n) desired = [ From 015641ae79daf89c444b2ccfe2e4d40d8ea6c1dd Mon Sep 17 00:00:00 2001 From: Pietro Berkes Date: Fri, 21 Jul 2023 11:32:19 +0200 Subject: [PATCH 4/4] Python is getting too fast for these simple tests --- big_o/complexities.py | 5 +++-- big_o/test/test_big_o.py | 8 ++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/big_o/complexities.py b/big_o/complexities.py index e1cbb56..ace8096 100755 --- a/big_o/complexities.py +++ b/big_o/complexities.py @@ -264,5 +264,6 @@ def coefficients(self): return np.exp(a), np.exp(b) -ALL_CLASSES = [Constant, Linear, Quadratic, Cubic, Polynomial, - Logarithmic, Linearithmic, Exponential] +ALL_CLASSES = [Constant, Logarithmic, Linear, Linearithmic, + Quadratic, Cubic, Polynomial, + Exponential] diff --git a/big_o/test/test_big_o.py b/big_o/test/test_big_o.py index afcce3b..3dd65ff 100755 --- a/big_o/test/test_big_o.py +++ b/big_o/test/test_big_o.py @@ -112,10 +112,10 @@ def test_big_o(self): # Each test case is a tuple # (function_to_evaluate, expected_complexity_class, range_for_n) desired = [ - (dummy_constant_function, compl.Constant, (1000, 10000)), - (dummy_linear_function, compl.Linear, (100, 5000)), + (dummy_constant_function, compl.Constant, (1000, 50000)), + (dummy_linear_function, compl.Linear, (100, 50000)), (dummy_quadratic_function, compl.Quadratic, (1, 100)), - (dummy_linearithmic_function, compl.Linearithmic, (10, 50000)), + (dummy_linearithmic_function, compl.Linearithmic, (100, 100000)), ] for func, class_, n_range in desired: res_class, fitted = big_o.big_o( @@ -124,7 +124,7 @@ def test_big_o(self): max_n=n_range[1], n_measures=25, n_repeats=1, - n_timings=10, + n_timings=3, return_raw_data=True) residuals = fitted[res_class]