SciML / ADTypes.jl

Repository for automatic differentiation backend types
https://sciml.github.io/ADTypes.jl/
MIT License
36 stars 11 forks source link

Pretty printing #64

Closed gdalle closed 4 weeks ago

gdalle commented 4 weeks ago

Checklist

Additional context

Right now every backend type is printed with its type parameters, which yields very long strings (especially with AutoSparse). Since I use those strings in DifferentiationInterface (e.g. as @testset names), I figured it would be nice to make them more user-friendly.

gdalle commented 4 weeks ago

Here's a before-after comparison.

Code

using ADTypes

struct FakeSparsityDetector <: ADTypes.AbstractSparsityDetector end
struct FakeColoringAlgorithm <: ADTypes.AbstractColoringAlgorithm end

for backend in [
    # dense
    AutoChainRules(; ruleconfig = :rc),
    AutoDiffractor(),
    AutoEnzyme(),
    AutoEnzyme(mode = :forward),
    AutoFastDifferentiation(),
    AutoFiniteDiff(),
    AutoFiniteDiff(fdtype = :fd, fdjtype = :fdj, fdhtype = :fdh),
    AutoFiniteDifferences(; fdm = :fdm),
    AutoForwardDiff(),
    AutoForwardDiff(chunksize = 3, tag = :tag),
    AutoPolyesterForwardDiff(),
    AutoPolyesterForwardDiff(chunksize = 3, tag = :tag),
    AutoReverseDiff(),
    AutoReverseDiff(compile = true),
    AutoSymbolics(),
    AutoTapir(),
    AutoTapir(safe_mode = false),
    AutoTracker(),
    AutoZygote(),
    # sparse
    AutoSparse(AutoForwardDiff()),
    AutoSparse(
        AutoForwardDiff();
        sparsity_detector = FakeSparsityDetector(),
        coloring_algorithm = FakeColoringAlgorithm()
    )
]
    println(backend)
end

Before

AutoChainRules{Symbol}(:rc)
AutoDiffractor()
AutoEnzyme{Nothing}(nothing)
AutoEnzyme{Symbol}(:forward)
AutoFastDifferentiation()
AutoFiniteDiff{Val{:forward}, Val{:forward}, Val{:hcentral}}(Val{:forward}(), Val{:forward}(), Val{:hcentral}())
AutoFiniteDiff{Symbol, Symbol, Symbol}(:fd, :fdj, :fdh)
AutoFiniteDifferences{Symbol}(:fdm)
AutoForwardDiff{nothing, Nothing}(nothing)
AutoForwardDiff{3, Symbol}(:tag)
AutoPolyesterForwardDiff{nothing, Nothing}(nothing)
AutoPolyesterForwardDiff{3, Symbol}(:tag)
AutoReverseDiff{false}(false)
AutoReverseDiff{true}(true)
AutoSymbolics()
AutoTapir(true)
AutoTapir(false)
AutoTracker()
AutoZygote()
AutoSparse{AutoForwardDiff{nothing, Nothing}, ADTypes.NoSparsityDetector, ADTypes.NoColoringAlgorithm}(AutoForwardDiff{nothing, Nothing}(nothing), ADTypes.NoSparsityDetector(), ADTypes.NoColoringAlgorithm())
AutoSparse{AutoForwardDiff{nothing, Nothing}, FakeSparsityDetector, FakeColoringAlgorithm}(AutoForwardDiff{nothing, Nothing}(nothing), FakeSparsityDetector(), FakeColoringAlgorithm())

After

AutoChainRules(ruleconfig=rc)
AutoDiffractor()
AutoEnzyme()
AutoEnzyme(mode=forward)
AutoFastDifferentiation()
AutoFiniteDiff()
AutoFiniteDiff(fdtype=fd, fdjtype=fdj, fdhtype=fdh)
AutoFiniteDifferences(fdm=fdm)
AutoForwardDiff()
AutoForwardDiff(chunksize=3, tag=tag)
AutoPolyesterForwardDiff()
AutoPolyesterForwardDiff(chunksize=3, tag=tag)
AutoReverseDiff()
AutoReverseDiff(compile=true)
AutoSymbolics()
AutoTapir()
AutoTapir(safe_mode=false)
AutoTracker()
AutoZygote()
AutoSparse(dense_ad=AutoForwardDiff())
AutoSparse(dense_ad=AutoForwardDiff(), sparsity_detector=FakeSparsityDetector(), coloring_algorithm=FakeColoringAlgorithm()))
ChrisRackauckas commented 4 weeks ago

The two argument show function is supposed to be round trippable. I don't think that's the case here since for example tag is not defined. You'd need to convert those back to symbols (and only when the input is symbol)

gdalle commented 4 weeks ago

You're right, that's an artefact of Symbol interpolation which removes the colon. Any idea how to get around it?

ChrisRackauckas commented 4 weeks ago

Directly use the roundtrip property of show, i.e. instead of trying to build a string and printing, do show on the parts as you build it.

julia> a = :s; b = :r;

julia> show(a); print(a)
:ss
julia> print("MyFunction(a = "); show(a); print(")") 
MyFunction(a = :s)
gdalle commented 4 weeks ago

The string building is useful to remove useless commas at the end. I found another workaround using repr(object, context=io), is that okay? Current result:

AutoChainRules(ruleconfig=:rc)
AutoDiffractor()
AutoEnzyme()
AutoEnzyme(mode=:forward)
AutoFastDifferentiation()
AutoFiniteDiff()
AutoFiniteDiff(fdtype=:fd, fdjtype=:fdj, fdhtype=:fdh)
AutoFiniteDifferences(fdm=:fdm)
AutoForwardDiff()
AutoForwardDiff(chunksize=3, tag=:tag)
AutoPolyesterForwardDiff()
AutoPolyesterForwardDiff(chunksize=3, tag=:tag)
AutoReverseDiff()
AutoReverseDiff(compile=true)
AutoSymbolics()
AutoTapir()
AutoTapir(safe_mode=false)
AutoTracker()
AutoZygote()
AutoSparse(dense_ad=AutoForwardDiff())
AutoSparse(dense_ad=AutoForwardDiff(), sparsity_detector=FakeSparsityDetector(), coloring_algorithm=FakeColoringAlgorithm()))
ChrisRackauckas commented 4 weeks ago

Yes repr is fine. It just uses show.

ChrisRackauckas commented 3 weeks ago

Shit I had just realized this won't round-trip properly because you need to re-wrap the symbols in Vals.

gdalle commented 3 weeks ago

In the example printing case I didn't provide Val's to the constructor so they're not showing up. I'll check tomorrow but I think we're good?