Git Product home page Git Product logo

sopt's Introduction

Sparse OPTimisation Library

build codecov DOI

Description

SOPT is an open-source C++ package available under the license below. It performs Sparse OPTimisation using state-of-the-art convex optimisation algorithms. It solves a variety of sparse regularisation problems, including the Sparsity Averaging Reweighted Analysis (SARA) algorithm.

SOPT also has several MPI wrappers that can be adapted for computational distirbution of various linear operators and convex optimisation algorithms. Wavelet Operators with SOPT also support multi-threading through OpenMP.

SOPT is written in C++ primarily but also contains partial and prototyped Matlab implementations of various algorithms.

SOPT is largely provided to support the PURIFY package, a companion open-source code to perform radio interferometric imaging, also written by the authors of SOPT. For further background please see the reference section.

This documentation outlines the necessary and optional dependencies upon which SOPT should be built, before describing installation and testing details and Matlab support. Contributors, references and license information then follows.

Dependencies installation

SOPT is mostly written in C++17. Pre-requisites and dependencies are listed in following and minimal versions required are tested against Travis CI meaning that they come natively with OSX and the Ubuntu Trusty release. These are also the default ones fetched by CMake.

C++ minimal dependencies:

  • CMake v3.9.2 A free software that allows cross-platform compilation.
  • GCC v7.3.0 GNU compiler for C++.
  • OpenMP v4.8.4 (Trusty) - Optional - Speeds up some of the operations.
  • Cppflow v2.0.0 - Optional - A warpper for the Tensorflow C API allowing us to read Tensorflow models into SOPT. Needed if you are using a learned prior.
  • Eigen3 v3.4.0 (Trusty) Modern C++ linear algebra. Downloaded automatically if absent.
  • Catch2 v3.4.0 - Optional - A C++ unit-testing framework only needed for testing. Downloaded automatically if absent.
  • google/benchmark - Optional - A C++ micro-benchmarking framework only needed for benchmarks. Downloaded automatically if absent.
  • tiff v4.5.1 (Trusty) Tag Image File Format library - only installed if needed.

Installing and building SOPT

Using Conan v2 (recommended)

Conan is a C++ package manager that helps deal with most of the C++ dependencies as well as the SOPT installation:

  1. If you are using a learned prior you must install the Tensorflow C API and cppflow package:

    • Install TensorFlow C API

    • Clone the UCL fork of cppflow and create a conan package using

      git clone [email protected]:UCL/cppflow.git
      conan create ./cppflow/

      Note that conan requires you to specify the host (h) and the build (b) profiles on the command line (-pr:b=default -pr:h=default or simply -pr:a=default), unless you have defined them in your conan profile. You can set up a default profile for your system using conan profile detect (only needs to be done once).

  2. Once the mandatory dependencies are present, git clone from the GitHub repository:

    git clone https://github.com/astro-informatics/sopt.git
  3. Then, the program can be built using conan:

    cd /path/to/code
    mkdir build
    cd build
    conan install .. -of . --build missing
    conan build .. -of .

Things to note:

  • To install in directory INSTALL_FOLDER, add the following options to the conan build command:

    conan build .. -of INSTALL_FOLDER
  • CMake build options should be passed as options to conan install using the -o flag with a value on or off. Possible options are:

    • tests (default on)
    • benchmarks (default off)
    • examples (default on)
    • openmp (default off)
    • dompi (default off)
    • docs (default off)
    • coverage (default off)
    • cppflow (default off)

For example, to build with both MPI and OpenMP on you would use

conan install .. -of . --build missing -o openmp=on -o dompi=on
conan build .. -of .

Using CMake

If the dependencies are already available on your system, you can also install SOPT manually like so

cd /path/to/code
mkdir build
cd build
cmake .. -DCMAKE_INSTALL_PREFIX=${PWD}/../local
make -j
make -j install

On MacOS, you can also install most of the dependencies with Homebrew e.g.

brew install libtensorflow eigen tiff catch2

Note that the ONNXruntime interface is currently only supported when compiling with Clang on MacOS, but not with g++

Conan tips

You can set commonly used options, choices of compilers etc. in a conan profile. You can list profiles available on your system using conan profile list and select the profile you want to use with conan install with conan install .. -pr my_profile. CMake build options can also be added to the profile under [options]. Here is an example of a conan profile for building with a homebrew installed gcc 11 on MacOS.

[settings]
os=Macos
os_build=Macos
arch=x86_64
arch_build=x86_64
compiler=gcc
compiler.version=11
compiler.libcxx=libstdc++11
build_type=Release
[options]
[build_requires]

Testing

To check everything went all right, run the test suite:

cd /path/to/code/build
ctest .

Matlab

A separate Matlab implementation is provided with SOPT. This implementation includes some (but not all) of the optimisation algorithms implemented in the C++ code, including the SARA algorithm.

The Matlab implementation is contained in the matlab directory. This is a stand-alone implementation and does not call any of the C++ code. In future, Matlab interfaces to the C++ code may also be included in SOPT.

See matlab/README.txt for an overview of the Matlab implementation. The stand-alone Matlab implementation is also self-documenting; corresponding documentation can be found in matlab/doc. We thank Gilles Puy for contributing to this Matlab implementation.

Contributors

Check the [contributors](@ref sopt_contributors) page (github).

References and citation

If you use SOPT for work that results in publication, please reference the webpage and our related academic papers:

  1. L. Pratley et al. (to be published)
  2. A. Onose, R. E. Carrillo, A. Repetti, J. D. McEwen, J.-P. Thiran, J.-C. Pesquet, and Y. Wiaux. "Scalable splitting algorithms for big-data interferometric imaging in the SKA era" Mon. Not. Roy. Astron. Soc. 462(4):4314-4335 (2016) arXiv:1601.04026
  3. R. E. Carrillo, J. D. McEwen, D. Van De Ville, J.-P. Thiran, and Y. Wiaux. "Sparsity averaging for compressive imaging" IEEE Signal Processing Letters 20(6):591-594 (2013) arXiv:1208.2330
  4. R. E. Carrillo, J. D. McEwen and Y. Wiaux. "Sparsity Averaging Reweighted Analysis (SARA): a novel algorithm for radio-interferometric imaging" Mon. Not. Roy. Astron. Soc. 426(2):1223-1234 (2012) arXiv:1205.3123

License

SOPT: Sparse OPTimisation package Copyright (C) 2013-2024

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details (LICENSE.txt).

You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

Webpage

Support

For any questions or comments, feel free to contact Jason McEwen, or add an issue to the issue tracker.

Notes

The code is given for educational purpose. For the Matlab version of the code see the folder matlab.

sopt's People

Contributors

20dm avatar cosmomatt avatar dpshelio avatar ilectra avatar jasonmcewen avatar krishnakumarg1984 avatar luke-pratley avatar mdavezac avatar mmcleod89 avatar olebole avatar rafael-carrillo avatar rc-softdev-admin avatar sinanshi avatar sjaffa avatar tkoskela avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

sopt's Issues

Add basic CG

Since the measurement operator and its adjoints should be functions, we can't always use Eigen's CG.
A first implementation might just wrap it though.

Implement prox L1

f(x, γ, Ψ) = min_{z} 0.5||x - z||_2^2 + λ||Ψ z||_1

aka sopt_prox_l1 in sopt_prox.c

Add regression testing framework

Some sort of framework in cmake so that we can easily test the new code vs the old code. It might
mean copying some of the C files to the test directory and keeping duplicates for now. Or adding
some way to download an old commit of the code, compile it and run against that.

Return l1 norm from l1 prox call

At present the l1 norm is recomputed outside of the l1 prox call. This could be avoided by having the l1 prox function return the last l1 norm, therefore avoiding the need to reapply Psit to the current image.

Functions needed by SDMM

  • sopt_utility_projposr: fancy speak for A = A.real; [A.real <= 0] = 0e0
  • sopt_utility_l1norm: sum w_i ||x_i||
  • sopt_utility_softth: sgn(x) * max(0, ||x|| - threshhold)
  • optionally, that sampling measurement thingie: sopt_meas_urandsamp
  • CG: see #26

Copyright statements, AUTHORS file

None of the files have copyright statements for now.
We could add one, although I'm not sure who holds the copyright (basp-group?)
The copyright could be updated to GPL3
An AUTHORS file could be added

Catch md5 changes too often

Catch has a fairly rapid development cycle. So checking MD5
when downloading the file fails unconveniently often. Since this is for tests only, I'll try to use
some other method to verify download.

Rename L1SDMM to SDMM

Implementation does not care what the $g_i$ objective functions are. L1 will be one of many possible
instanciation when creating the SDMM operator. So not a good name.

Revisit convergence criteria for SDMM

Right now, I'm just using iter < itermax and a user specified functions.
But maybe we could use the $z ~ \sum_i x_i - prox(x_i)$ + user function.

Outside of memory range write in padmm

in the file sopt_l1.c, in padmm, we have:

// Copy r in such a way so that as it can be read as real data
// in the real-complex case (xsol used for temporary storage).
if (param.real_out == 1 && param.real_meas == 0) {
for (i = 0; i < nx; i++){
*((double*)xsol + i) = creal(*((complex double*)r + i));

*((complex double*)r + i) = 0.0 +0.0*I;
}
for (i = 0; i < nx; i++)
*((double*)r + i) = *((double*)xsol + i);
*((double*)xsol + i) = 0.0;
}

The second to last line should likely be in the last for-loop.

Consistent naming convention for solvers

Since we've added and are adding a number of new solvers, we probably need to develop a consistent naming approach. For example, we currently have sopt_l1_solver (Douglas-Rachford), sopt_l1_sdmm (SDMM) and sopt_l1_solver_aadmm (approximate ADMM), and also reweighted versions. In future, we might also like to support the unconstrained, as well as the constrained problem (i.e. + lambda * data fidelity term).

Renaming will be a bit of a pain, since it would be a breaking change, but it's probably best to sort out now rather than later (we can also add in old interfaces that could be depreciated in time).

How about sopt_l1_solver_? For example, sopt_l1_solver_constrained_aadmm_rw or sopt_l1_solver_unconstrained_sdmm. Or is that convention too heavy?

@rafael-carrillo @mdavezac @vijaykartik Thoughts? Suggestions?

Add general SDMM operator

General framework seeks to minimize $\sum_i g_i(L_i*x)$. It takes as input a list of operators
consisting of:

  • L_i
  • L_i^\dagger
  • the proximal of g_i

It might/can also take as input a conjugate gradient method, a convergence criteria, itermax, gamma,
... something else?

Move gbenchmark back to original

Small bug on google/gbenchmark prevents compilation.
Once google/gbenchmark#152 is fixed, we should move back to tracking it rather than my fork.

Make FISTA optimisation of l1 prox optional

FISTA only helps with many sub-iterations are required. For the inexact ADMM we look for inexact solutions so we don't need to run so many sub-iterations. We could get a performance saving by turning FISTA off since it requires a lot of additional memory.

Random numbers

Some general way to handle random numbers.
Right-now, only used in sampling operator.
It might be the sampling operator should take an argument for the random number generator.

More descriptive error messages in c++ and python

In [2]: import wavelets.wavelets as wv
In [3]: import numpy as np
In [4]: input = np.random.random(128)
In [5]: wv.dwt(input,"xyz",1)
---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
<ipython-input-5-71b4d0f139bc> in <module>()
----> 1 wv.dwt(input,"xyz",1)
wavelets.pyx in wavelets.dwt (python/wavelets/cython_wavelets.cc:2989)()
wavelets.pyx in wavelets._rdwt (python/wavelets/cython_wavelets.cc:2173)()
RuntimeError: std::exception

That really does not explain what went wrong, neither in python nor in C++.
For #38 or later.

Benchmarking for sdmm

Probably some in-painting example with random images of different sizes, and different wavelets
basis.

Future improvements to interface

Currently WSClean exposes these functions:

void wsclean_initialize(void** userData, const struct purify_domain_info* domain_info, struct purify_domain_data_format* data_info);
void wsclean_read(void* userData, DCOMPLEX* data, double* weights);
void wsclean_write(void* userData, const double* image);
void wsclean_deinitialize(void* userData);
void wsclean_operator_A(void* dataIn, void* dataOut, void* userData);
void wsclean_operator_At(void* dataIn, void* dataOut, void* userData);

For neatness, I suggest two more changes. Maybe not really necessary for now during the hack week, but nice to think about in the future:

  • The initialize method can return function pointers to the other functions. That way, the only function call you need to know about is the initialization function. These functions pointers can be stored in what is currently the 'purify_domain_data_format' structure, but maybe rename it. So, Purify would do something like this:
    wsclean_initialize(&userdata, &dinfo, &formatinfo);
    read_function=formatinfo.read_function
    deinitialize_function=formatinfo.deinitializate_function
    ...
    (_read_function) (userdata, parameters)
    ...
    (_deinitialize_function) (userdata)
  • The measurement operator functions (for wsclean; wsclean_operator_A and wsclean_operator_At) should be fully typed, be const correct and for consistency start with the userdata parameter:
    void wsclean_operator_A(void* userData, const double* dataIn, double complex* dataOut);
    void wsclean_operator_At(void* userData, const double complex* dataIn, double* dataOut);
    Purify should cast the function pointers when necessary to e.g. support double->double measurement operators, instead of casting the parameters everytime in both the callee and caller.

makefile is broken

$ make
make: *** No rule to make target `../sopt/src/c/sopt_error.o', needed by `../sopt/lib/libsopt.a'.  Stop.

probably it should be removed.

Check logging setup

In purify example, changing the logging level in initialized does not seem to work...

refactored wavelet enhancement

At this juncture there are still further enhancements that might be beneficial to the (refactored)
wavelet code:

  • remove const_cast and use rvalue reference overloads instead. const_cast is the canonical
    Eigen way of doing things, but it is quite ugly.
  • 2d and 1d code could be consolidated if the 2d operations are always colwise and rowwise (which I
    think they are)
  • periodic_scalar_product could be made to use eigen functions only, without an explicit loop.
  • nominally, we only need as much memory as N by rows, where N is the number of wavelet
    coefficients.

Add install/export framework

It should be possible to install sopt to disk somewhere. And it should register itself so other
CMake projects can find it.
This is done in the "old" version. Needs to be updated for refactoring.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.