diff --git a/.github/workflows/run_tests.yml b/.github/workflows/run_tests.yml index 1c25d13f..30a4dc41 100644 --- a/.github/workflows/run_tests.yml +++ b/.github/workflows/run_tests.yml @@ -14,31 +14,34 @@ env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} jobs: - build: - - runs-on: ubuntu-latest + test: + # Use older version of ubuntu for Python 3.6. + runs-on: ${{ matrix.python-version == '3.6' && 'ubuntu-20.04' || 'ubuntu-latest' }} strategy: fail-fast: false matrix: - python-version: ["3.6", "3.7", "3.8", "3.9"] + python-version: ["3.6", "3.7", "3.8", "3.9", "3.10", "3.11"] steps: - uses: actions/checkout@v3 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v3 + uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} - name: Install dependencies run: | python -m pip install --upgrade pip - python -m pip install numpy scipy matplotlib seaborn pip nose cvxpy setuptools coveralls numexpr + python -m pip install numpy scipy matplotlib seaborn pip nose2 cvxpy setuptools + python -m pip install coveralls numexpr pymanopt if [ -f requirements.txt ]; then pip install -r requirements.txt; fi python setup.py install - name: Install additional dependencies - if: ${{ matrix.python-version != '3.8' && matrix.python-version != '3.9' }} + # Install backport of dataclasses for pymanopt dependency on Python < 3.7. + if: ${{ matrix.python-version < '3.7' }} run: | - python -m pip install tensorflow==1.15.2 pymanopt + python -m pip install dataclasses - name: Test run: | - coverage run test.py tests/* - coveralls --service=github \ No newline at end of file + coverage run --source=tests -m nose2 + coverage report -m + coveralls --service=github diff --git a/README.md b/README.md index 7f3a04bc..3d81a749 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,19 @@ # equadratures -*equadratures* is an open-source library for *uncertainty quantification*, *machine learning*, *optimisation*, *numerical integration* and *dimension reduction* -- all using orthogonal polynomials. It is particularly useful for models / problems where output quantities of interest are smooth and continuous; to this extent it has found widespread applications in computational engineering models (finite elements, computational fluid dynamics, etc). It is built on the latest research within these areas and has both deterministic and randomised algorithms. +_equadratures_ is an open-source library for _uncertainty quantification_, _machine learning_, _optimisation_, _numerical integration_ and _dimension reduction_ -- all using orthogonal polynomials. It is particularly useful for models / problems where output quantities of interest are smooth and continuous; to this extent it has found widespread applications in computational engineering models (finite elements, computational fluid dynamics, etc). It is built on the latest research within these areas and has both deterministic and randomised algorithms. **Key words associated with this code**: polynomial surrogates, polynomial chaos, polynomial variable projection, Gaussian quadrature, Clenshaw Curtis, polynomial least squares, compressed sensing, gradient-enhanced surrogates, supervised learning. ## Code -The latest version of the code is v10 *Baby Blue*, released March 2022. +The latest version of the code is v10 _Baby Blue_, released March 2022. ![](https://travis-ci.com/equadratures/equadratures.svg?branch=master) -[![](https://coveralls.io/repos/github/equadratures/equadratures/badge.svg?branch=master)](https://coveralls.io/github/Effective-Quadratures/Effective-Quadratures) +[![](https://coveralls.io/repos/github/equadratures/equadratures/badge.svg?branch=master)](https://coveralls.io/github/equadratures/equadratures) [![](https://badge.fury.io/py/equadratures.svg)](https://pypi.org/project/equadratures/) [![](https://joss.theoj.org/papers/10.21105/joss.00166/status.svg)](https://joss.theoj.org/papers/10.21105/joss.00166) [![](https://img.shields.io/pypi/pyversions/equadratures.svg)](https://pypi.python.org/pypi/equadratures) -![](https://img.shields.io/github/stars/Effective-Quadratures/Effective-Quadratures.svg?style=flat-square&logo=github&label=Stars&logoColor=white) +![](https://img.shields.io/github/stars/equadratures/equadratures.svg?style=flat-square&logo=github&label=Stars&logoColor=white) ![](https://static.pepy.tech/badge/equadratures/week) [![](https://img.shields.io/discourse/status?server=https%3A%2F%2Fdiscourse.equadratures.org)](https://discourse.equadratures.org) @@ -23,11 +23,11 @@ If you use `pip` you can install the code with: pip install equadratures ``` -or `pip` can be replaced with `python -m pip`, where `python` is the python version you wish to install *equadratures* for. Use of a virtual enviroment such as [virtualenv](https://pypi.org/project/virtualenv/) or [pyenv](https://github.com/pyenv/pyenv)/[pipenv](https://pypi.org/project/pipenv/) is also encouraged. Alternatively you can click either on the **Fork Code** button or **Clone**, and install from your local version of the code. +or `pip` can be replaced with `python -m pip`, where `python` is the python version you wish to install _equadratures_ for. Use of a virtual enviroment such as [venv](https://docs.python.org/3/library/venv.html) or [pipenv](https://pypi.org/project/pipenv/) is also encouraged. Alternatively you can click either on the **Fork Code** button or **Clone**, and install from your local version of the code. -For issues with the code, please do *raise an issue* on our Github page; do make sure to add the relevant bits of code and specifics on package version numbers. We welcome contributions and suggestions from both users and folks interested in developing the code further. +For issues with the code, please do _raise an issue_ on our Github page; do make sure to add the relevant bits of code and specifics on package version numbers. We welcome contributions and suggestions from both users and folks interested in developing the code further. -Our code is designed to require minimal dependencies; current package requirements include ``numpy``, ``scipy`` and ``matplotlib``. +Our code is designed to require minimal dependencies; current package requirements include `numpy`, `scipy` and `matplotlib`. ## Documentation, tutorials, Discourse @@ -39,24 +39,23 @@ We've recently started a Discourse forum! Check it out [here](https://discourse. Specific goals of this code include: -* probability distributions and orthogonal polynomials -* supervised machine learning: regression and compressive sensing -* numerical quadrature and high-dimensional sampling -* transforms for correlated parameters -* computing moments from models and data-sets -* sensitivity analysis and Sobol' indices -* data-driven dimension reduction -* ridge approximations -* surrogate-based design optimisation +- probability distributions and orthogonal polynomials +- supervised machine learning: regression and compressive sensing +- numerical quadrature and high-dimensional sampling +- transforms for correlated parameters +- computing moments from models and data-sets +- sensitivity analysis and Sobol' indices +- data-driven dimension reduction +- ridge approximations +- surrogate-based design optimisation ## Get in touch -Feel free to follow us via [Twitter](https://twitter.com/EQuadratures) or email us at mail@equadratures.org. - +Feel free to follow us via [Twitter](https://twitter.com/EQuadratures) or email us at mail@equadratures.org. ## Community guidelines -If you have contributions, questions, or feedback use either the Github repository, or get in touch. We welcome contributions to our code. In this respect, we follow the [NumFOCUS code of conduct](https://numfocus.org/code-of-conduct). +If you have contributions, questions, or feedback use either the Github repository, or get in touch. We welcome contributions to our code. In this respect, we follow the [NumFOCUS code of conduct](https://numfocus.org/code-of-conduct). ## Acknowledgments diff --git a/equadratures/logistic_poly.py b/equadratures/logistic_poly.py index 3a4a078d..869ec8d7 100644 --- a/equadratures/logistic_poly.py +++ b/equadratures/logistic_poly.py @@ -9,7 +9,7 @@ if manopt: from pymanopt.manifolds import Stiefel from pymanopt import Problem - from pymanopt.solvers import ConjugateGradient + from pymanopt.optimizers import ConjugateGradient class LogisticPoly(object): """ @@ -159,16 +159,21 @@ def fit(self, X_train, f_train): if self.verbosity == 2: print('residual = %f' % residual) residual_history.append(residual) - # Minimize over M - func_M = lambda M_var: self._cost(f, X, M_var, c) - grad_M = lambda M_var: self._dcostdM(f, X, M_var, c) manifold = Stiefel(d, n) - solver = ConjugateGradient(maxiter=self.max_M_iters) + solver = ConjugateGradient(max_iterations=self.max_M_iters) + + # Minimize over M + @pymanopt.function.numpy(manifold) + def func_M(M_var): + return self._cost(f, X, M_var, c) + @pymanopt.function.numpy(manifold) + def grad_M(M_var): + return self._dcostdM(f, X, M_var, c) - problem = Problem(manifold=manifold, cost=func_M, egrad=grad_M, verbosity=0) + problem = Problem(manifold=manifold, cost=func_M, euclidean_gradient=grad_M) - M = solver.solve(problem, x=M) + M = solver.run(problem, initial_point=M).point # Minimize over c func_c = lambda c_var: self._cost(f, X, M, c_var) diff --git a/equadratures/optimisation.py b/equadratures/optimisation.py index a6c780bd..201b4abb 100644 --- a/equadratures/optimisation.py +++ b/equadratures/optimisation.py @@ -59,7 +59,7 @@ def add_objective(self, poly=None, custom=None, maximise=False): f = poly.get_polyfit_function() jac = poly.get_polyfit_grad_function() hess = poly.get_polyfit_hess_function() - objective = lambda x: k*np.asscalar(f(x)) + objective = lambda x: k*f(x).item() objective_deriv = lambda x: k*jac(x)[:,0] objective_hess = lambda x: k*hess(x)[:,:,0] elif custom is not None: @@ -247,7 +247,7 @@ def add_nonlinear_eq_con(self, poly=None, custom=None): g = poly.get_polyfit_function() jac = poly.get_polyfit_grad_function() hess = poly.get_polyfit_hess_function() - constraint = lambda x: np.asscalar(g(x)) + constraint = lambda x: g(x).item() constraint_deriv = lambda x: jac(x)[:,0] constraint_hess = lambda x, v: hess(x)[:,:,0] if self.method == 'trust-constr': @@ -341,7 +341,7 @@ def optimise(self, x0, *args, **kwargs): def _set_iterate(self): ind_min = np.argmin(self.f) self.s_old = self.S[ind_min,:] - self.f_old = np.asscalar(self.f[ind_min]) + self.f_old = self.f[ind_min].item() self._update_bounds() def _set_del_k(self, value): @@ -406,7 +406,7 @@ def _blackbox_evaluation(self, s): else: self.S = np.vstack((self.S, s)) self.f = np.vstack((self.f, f)) - return np.asscalar(f) + return f.item() def _update_bounds(self): if self.bounds is not None: @@ -842,10 +842,10 @@ def _compute_step(self, my_poly): for i in range(self.n): bounds.append((self.bounds_l[i], self.bounds_u[i])) if self.method == 'trust-region': - res = optimize.minimize(lambda x: np.asscalar(my_poly.get_polyfit(x)), self.s_old, method='TNC', \ + res = optimize.minimize(lambda x: my_poly.get_polyfit(x).item(), self.s_old, method='TNC', \ jac=lambda x: my_poly.get_polyfit_grad(x).flatten(), bounds=bounds, options={'disp': False}) elif self.method == 'omorf': - res = optimize.minimize(lambda x: np.asscalar(my_poly.get_polyfit(np.dot(x,self.U))), self.s_old, \ + res = optimize.minimize(lambda x: my_poly.get_polyfit(np.dot(x,self.U)).item(), self.s_old, \ method='TNC', jac=lambda x: np.dot(self.U, my_poly.get_polyfit_grad(np.dot(x,self.U))).flatten(), \ bounds=bounds, options={'disp': False}) s_new = res.x @@ -932,7 +932,7 @@ def _trust_region(self, s_old, del_k, rho_min, eta_1, eta_2, gam_dec, gam_inc, g S, f = self._sample_set('replace', S, f, s_new, f_new) # Calculate trust-region factor del_f = self.f_old - f_new - del_m = np.asscalar(my_poly.get_polyfit(self.s_old)) - m_new + del_m = np.ndarray.item(my_poly.get_polyfit(self.s_old)) - m_new if abs(del_m) < 100*np.finfo(float).eps: self._set_ratio(1.0) else: @@ -994,7 +994,7 @@ def _omorf(self, s_old, d, subspace_method, del_k, rho_min, eta_1, eta_2, gam_de return # Calculate trust-region factor del_f = self.f_old - f_new - del_m = np.asscalar(my_poly.get_polyfit(np.dot(self.s_old,self.U))) - m_new + del_m = np.ndarray.item(my_poly.get_polyfit(np.dot(self.s_old,self.U))) - m_new if abs(del_m) < 100*np.finfo(float).eps: self._set_ratio(1.0) else: diff --git a/equadratures/sampling_methods/induced.py b/equadratures/sampling_methods/induced.py index f4cdd51a..69d64f74 100644 --- a/equadratures/sampling_methods/induced.py +++ b/equadratures/sampling_methods/induced.py @@ -409,7 +409,7 @@ def induced_jacobi_evaluation(self, alpha, beta, x, parameter, alpha*np.log(2.0) - betaln(beta+1.0, alpha+1.0) - np.log(beta+1.0)+(beta+1)*np.log((x+1.0)/2.0))*integral - F = np.asscalar(F) + F = F.item() if _complementary: F = 1-F diff --git a/equadratures/solver.py b/equadratures/solver.py index 21f148da..be21139d 100644 --- a/equadratures/solver.py +++ b/equadratures/solver.py @@ -490,7 +490,7 @@ def _l1qc_newton(x0, u0, A, b, epsilon, tau, newtontol, newtonmaxiter, cgtol, cg r = np.dot(A, x).flatten() - b.flatten() fu1 = x - u fu2 = -x - u - fe = 0.5*(np.asscalar(np.dot(r.T,r)) - epsilon**2) + fe = 0.5*(np.dot(r.T,r).item() - epsilon**2) f = np.sum(u) - (1.0/tau) * (np.sum(np.log(-fu1)) + np.sum(np.log(-fu2)) + np.log(-fe)) niter = 0 @@ -531,7 +531,7 @@ def _l1qc_newton(x0, u0, A, b, epsilon, tau, newtontol, newtonmaxiter, cgtol, cg # minimum step size that stays in the interior aqe = np.dot(Adx.T, Adx) bqe = 2.0*np.dot(r.T, Adx) - cqe = np.asscalar(np.dot(r.T,r)) - epsilon**2 + cqe = np.dot(r.T,r).item() - epsilon**2 smax = np.min(np.hstack([ 1.0,np.min(np.hstack([-fu1[(dx-du) > 0] / (dx[(dx-du) > 0] - du[(dx-du) > 0]),\ -fu2[(-dx-du) > 0] / (-dx[(-dx-du) > 0] - du[(-dx-du) > 0]), \ diff --git a/equadratures/subspaces.py b/equadratures/subspaces.py index 4029ca05..70847c00 100644 --- a/equadratures/subspaces.py +++ b/equadratures/subspaces.py @@ -526,11 +526,11 @@ def get_samples_constraining_active_coordinates(self, inactive_samples, active_c f, g = b - np.dot(A, z0), np.dot(A, d) # find an upper bound on the step - min_ind = np.logical_and(g <= 0, f < -np.sqrt(np.finfo(np.float).eps)) + min_ind = np.logical_and(g <= 0, f < -np.sqrt(np.finfo(np.float64).eps)) eps_max = np.amin(f[min_ind] / g[min_ind]) # find a lower bound on the step - max_ind = np.logical_and(g > 0, f < -np.sqrt(np.finfo(np.float).eps)) + max_ind = np.logical_and(g > 0, f < -np.sqrt(np.finfo(np.float64).eps)) eps_min = np.amax(f[max_ind] / g[max_ind]) # randomly sample eps @@ -662,7 +662,7 @@ def jacobian_vp(V, V_plus, U, f, Polybasis, eta, minmax, X): current = Gradient[l].T if n == 1: current = Gradient.T - dV[:,l,:,j] = np.asscalar(vectord[l])*(X.T*current[:,j]) + dV[:,l,:,j] = vectord[l].item()*(X.T*current[:,j]) # Get the P matrix P = np.identity(M)-np.matmul(V,V_plus) diff --git a/test.py b/test.py deleted file mode 100644 index debf9028..00000000 --- a/test.py +++ /dev/null @@ -1,6 +0,0 @@ -# #!/usr/bin/env python -# import matplotlib -import nose -# matplotlib.use('agg') - -nose.main()