Skip to content

Commit

Permalink
Merge pull request #282 from bnubald/develop
Browse files Browse the repository at this point in the history
Fixes, dependency updates, and working transition to GitHub Actions.
  • Loading branch information
bnubald committed May 24, 2023
2 parents 9a46722 + 4019468 commit ce2a6ad
Show file tree
Hide file tree
Showing 8 changed files with 57 additions and 56 deletions.
23 changes: 13 additions & 10 deletions .github/workflows/run_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
coverage run --source=tests -m nose2
coverage report -m
coveralls --service=github
37 changes: 18 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
@@ -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)

Expand All @@ -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

Expand All @@ -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

Expand Down
19 changes: 12 additions & 7 deletions equadratures/logistic_poly.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
"""
Expand Down Expand Up @@ -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)
Expand Down
16 changes: 8 additions & 8 deletions equadratures/optimisation.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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':
Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand Down
2 changes: 1 addition & 1 deletion equadratures/sampling_methods/induced.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions equadratures/solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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]), \
Expand Down
6 changes: 3 additions & 3 deletions equadratures/subspaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down
6 changes: 0 additions & 6 deletions test.py

This file was deleted.

0 comments on commit ce2a6ad

Please sign in to comment.