Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Algorithms refactoring #18

Merged
merged 15 commits into from
May 12, 2019

Conversation

lostella
Copy link
Member

@lostella lostella commented Feb 22, 2019

This is a work in progress, but I thought it's better to open a CR already before we discuss about #17

Edit

Adding a bit of description. This PR is meant to:

  • remove any occurrence of Tuple{AbstractArray} in favor of just AbstractArray (with the idea of using ArrayPartition in place of Tuple, whenever this is needed)
  • restructure the iterables structure, splitting what is supposed to be immutable (that goes into the iterable) from what is mutable (that goes in the iteration state)
  • simplify the code of the algorithms, where possible (for example, in forward-backward-based iterations)
  • potentially update/unify the interface the different algorithms (in the sense of making homogeneous: similar structure of required vs optional arguments, similar requirements in terms of stepsizes vs Lipschitz constants, and so on)

Todo list:

  • add iteration tools and L-BFGS
  • upgrade forward-backward splitting
  • upgrade PANOC
  • upgrade ZeroFPR
  • upgrade AFBA
  • upgrade Douglas-Rachford splitting
  • add Davis-Yin splitting
  • sort out tests better
  • add Davis-Yin to the README
  • move ArrayPartition-related definitions in tests
  • tests on problems with multiple blocks of variables, using ArrayPartition
  • remove REQUIRE files, add Project.toml (see here)
  • tests with Float16/Float32/Complex
  • add type annotations to problem terms in iterators
  • save further allocations in FBS and PANOC
  • enforce code style conventions
  • make sure all previous tests are re-included
  • make test coverage great again

Edit 2: this should fix #12, #16, and #19

@lostella lostella mentioned this pull request Feb 22, 2019
@nantonel
Copy link
Collaborator

aren't these PR complementary somehow?

@lostella
Copy link
Member Author

I think this clashes with #17 since it modifies the algorithms code in many places; on the other hand, this includes #17, since it also removes the dependency on tuples.

This said, it's perfectly fine for me to merge #17 (as soon as it works) and then I'll rebase this PR on top of that. I would just avoid doing unnecessary work, for example if making #17 work requires time and then this PR overwrites it almost completely.

@nantonel
Copy link
Collaborator

Well as you can see #17 does not have major changes. However perhaps it's safer to close #17 and directly remove BlockArrays in this PR.

@nantonel
Copy link
Collaborator

I see that you have the LBFGS operator here. Shouldn't we keep it in one place only? Personally I would prefer having it in AbstractOperators although I see that it belongs to this package as well.

@lostella
Copy link
Member Author

lostella commented Mar 2, 2019

@nantonel it's ok to duplicate code in this case in my opinion (since here it's not really user-facing) in favor of having more compact code: anyone wanting to dig into L-BFGS-based algorithms only needs to explore this package.

@codecov-io
Copy link

codecov-io commented Mar 2, 2019

Codecov Report

Merging #18 into master will increase coverage by 1.52%.
The diff coverage is 93.91%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master      #18      +/-   ##
==========================================
+ Coverage   92.41%   93.93%   +1.52%     
==========================================
  Files          12       12              
  Lines         593      445     -148     
==========================================
- Hits          548      418     -130     
+ Misses         45       27      -18
Impacted Files Coverage Δ
src/ProximalAlgorithms.jl 100% <ø> (+22.22%) ⬆️
src/compat.jl 0% <0%> (ø)
src/utilities/fbetools.jl 100% <100%> (ø)
src/utilities/iterationtools.jl 100% <100%> (ø)
src/utilities/conjugate.jl 100% <100%> (ø) ⬆️
src/algorithms/davisyin.jl 100% <100%> (ø)
src/algorithms/douglasrachford.jl 100% <100%> (ø)
src/algorithms/primaldual.jl 82.27% <82.27%> (ø)
src/algorithms/zerofpr.jl 94.59% <94.59%> (ø)
src/algorithms/panoc.jl 95.5% <95.5%> (ø)
... and 12 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update b9a4085...1268a2d. Read the comment docs.

@nantonel nantonel mentioned this pull request Mar 7, 2019
3 tasks
@coveralls
Copy link

Coverage Status

Coverage decreased (-29.2%) to 60.599% when pulling f115ac0 on lostella:algorithms-refactoring into ad924db on kul-forbes:master.

@coveralls
Copy link

coveralls commented Mar 22, 2019

Coverage Status

Coverage increased (+4.6%) to 93.98% when pulling 9267c9e on lostella:algorithms-refactoring into b9a4085 on kul-forbes:master.

@lostella
Copy link
Member Author

I still need to finish up a bit with tests (it would be great to re-include tests using SeparableSum and ArrayPartition), but I'm fairly satisfied with the rest of the refactoring.

I would kindly ask reviews from @nantonel (in particular: changes in the algorithms APIs and their implications on higher level packages, i.e. StructuredOptimization.jl) and @pylat (in particular: primal-dual algorithms and tests).

@lostella lostella requested review from nantonel and pylat April 14, 2019 13:24
Copy link
Contributor

@pylat pylat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks quite nice and clean. I must confess, I didn't check thoroughly. Everything that I checked seems to be in order. I am annoyed by this ugly stepsize selection but I remember that it was inevitable.

@lostella
Copy link
Member Author

Thanks, Puya. I think the default selection for gamma1 and gamma2 is fine, however complicated, as long as it's well separated from the rest of the code (interface, initialization, iteration). It's also much better than having people have to manually select gamma1 and gamma2, of course :-)

Copy link
Collaborator

@nantonel nantonel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this hard work! I've made some minor comments: I suppose a couple of allocations could be reduced and some type instability fixed (especially in DRS family) but perhaps we can leave this to future PRs. I suppose we could enable verbose in some tests, should slightly improve coverage? Before tagging a new version, let's wait and fix StructOpt first.

REQUIRE Outdated Show resolved Hide resolved
src/utilities/arraypartition.jl Outdated Show resolved Hide resolved

struct DRS_iterable{R <: Real, C <: Union{R, Complex{R}}, T <: AbstractArray{C}}
f
g
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

f and g shouldn't be typed? of course this can be fixed on a later PR.

Copy link
Member Author

@lostella lostella May 10, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Of course they should. And I should be less lazy :-p

I'm adding all these to the TODO list on top, and will add the changes before merging

end

function Base.iterate(iter::FBS_iterable{R}, state::FBS_state{R, Tx, TAx}) where {R, Tx, TAx}
Az, f_Az, grad_f_Az, At_grad_f_Az = nothing, nothing, nothing, nothing
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but this could be initialised already when constructing state in Base.iterate(iter::FBS_iterable{R})?
Or am I wrong?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You mean having additional fields for these in the state? Yes, that could be, that could save some allocations I guess?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I've addressed everything except for this: I would open a separate issue and leave it to a separate PR, from what I've seen algorithms perform already very good like this

end

function Base.iterate(iter::PANOC_iterable{R}, state::PANOC_state{R, Tx, TAx}) where {R, Tx, TAx}
Az, f_Az, grad_f_Az, At_grad_f_Az = nothing, nothing, nothing, nothing
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same comment as above

g
h
l
L
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as DRS

@lostella
Copy link
Member Author

@nantonel I think coverage is OK now: one thing to do is removing Coveralls also here, since it is more confusing than useful.

Of course we’ll wait before tagging: we first need to understand how package registration now works :D

@lostella lostella merged commit 09ccc63 into JuliaFirstOrder:master May 12, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Implement Davis-Yin splitting
5 participants