Convex.jl
Convex.jl copied to clipboard
Document atoms
Just exploring a few options:
https://jump.dev/Convex.jl/previews/PR610/manual/atoms/
Codecov Report
Attention: Patch coverage is 98.32636%
with 4 lines
in your changes missing coverage. Please review.
Project coverage is 98.21%. Comparing base (
459f86b
) to head (8598f8a
).
Files | Patch % | Lines |
---|---|---|
src/supported_operations.jl | 98.19% | 4 Missing :warning: |
Additional details and impacted files
@@ Coverage Diff @@
## master #610 +/- ##
=======================================
Coverage 98.21% 98.21%
=======================================
Files 89 87 -2
Lines 5198 5198
=======================================
Hits 5105 5105
Misses 93 93
:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.
the current docs are kind of centered around the constructor functions rather than the structs, since usually users should use the former. I think though it definitely is nice to document the actual primitives that are available. I think maybe it could be most useful to keep the functions as the first thing the users see/interact with, and add docstrings to them, and then have the atoms as more advanced docs.
the current docs are kind of centered around the constructor functions rather than the structs, since usually users should use the former
Yeah... I've realized this. I just wondered about adding docstrings for Base.abs
, etc. But perhaps it's okay.
I don't really have a good solution yet.
There's also: https://jump.dev/Convex.jl/previews/PR610/manual/operations/
But it doesn't have every atom or reformulation (e.g., abs2
is missing).
I also wonder about how important the DCP rules are. I don't think many people are computing the rules in their head from the docs? They probably just try it to see if it works.
What are thoughts on https://jump.dev/Convex.jl/previews/PR610/atoms/
Too verbose? What parts are useful?
I like it! IMO not too verbose. In fact I think the reformulations could be more verbose. I think the examples are quite useful, and I like the mini table too about convexity properties. I find them useful at least, and I think when folks are debugging stuff it comes in handy.
In fact I think the reformulations could be more verbose
Yes, if we're not focusing on atoms, then it makes sense to have these identical.
I even wonder if it makes sense to move all of the Base.abs
etc methods to a single operators.jl
file. The atoms (as in, the structs) are standalone, and how exactly we implement the operators is independent. We might, for example, decide to rewrite some of the existing "reformulations" to become atoms, but that wouldn't change the public interface.
true, and we have done that in the past (though often the other way, deleting slow or buggy atoms in favor of reformulations)
I don't know if this needs to block the release
It does not, you can remove it from the milestone if this PR is not ready to merge
@blegat thoughts on keeping the operators in a separate file or keep with atom structs?
Here's a script to rebuild the doclist
function build_atoms_md(input_filename, filename)
data = read(input_filename, String);
reform = joinpath(dirname(input_filename), "reformulations")
for file in readdir(reform; join = true)
data *= read(file, String)
end
header = """# Atoms
Convex.jl supports the following functions. These functions may be composed
according to the [DCP](http://dcp.stanford.edu) composition rules to form new
convex, concave, or affine expressions.
"""
open(filename, "w") do io
return print(io, header)
end
block_fn = r"\"\"\"\nfunction (.+?\(.+?\))"ms
inline_fn = r"\"\"\"\n([a-zA-Z0-9\_\.\:\+\-\*\/\^]+\(.+?\)) = "m
function fn_name(x)
x = replace(x, "Base." => "", "LinearAlgebra." => "", ":" => "")
return String(x[1:(only(findfirst("(", x))-1)])
end
args = Dict{String,Vector{String}}()
block_fns = collect(eachmatch(block_fn, data))
inline_fns = collect(eachmatch(inline_fn, data))
for m in vcat(block_fns, inline_fns)
is_public = occursin("Base.", m[1]) ||
occursin("LinearAlgebra.", m[1]) ||
Symbol(fn_name(m[1])) in names(Convex)
if !is_public
continue # Not exported
end
signature = replace(
m[1],
r"[a-zA-Z]+?::" => "::",
"LinearAlgebra." => "Convex.",
"AbstractExpr" => "Convex.AbstractExpr",
"Value" => "Convex.Value",
"Constant" => "Convex.Constant",
)
if !(startswith(signature, "Base.") || startswith(signature, "Convex."))
signature = "Convex.$signature"
end
push!(get!(args, fn_name(m[1]), String[]), signature)
end
open(filename, "a") do io
for name in sort(collect(keys(args)))
signature = join(sort(args[name]), "\n")
println(
io,
"""
## `$name`
```@docs
$signature
```
""",
)
end
return
end
return
end
build_atoms_md("src/supported_operations.jl", "docs/src/manual/atoms.md")
@blegat thoughts on keeping the operators in a separate file or keep with atom structs?
I like it in a separate file
So what do we think about this?
I've moved this to the API reference, so I think I'm going to merge, unless there are other comments.