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

Move the docs over from ChainRules #115

Merged
merged 26 commits into from
Jan 22, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
6e19fad
Add documentation setup (#4)
ararslan Apr 2, 2019
d64774b
Add basic documentation
ararslan Apr 2, 2019
40f7869
Add basic docs for Rule
ararslan Apr 3, 2019
f972084
rework docs section to prep for planned content + API docstrings. als…
jrevels Apr 10, 2019
f38a72f
fix typo
jrevels Apr 10, 2019
57fdc0e
Fix documentation to use ChainRulesCore
nickrobinson251 Aug 11, 2019
d04fb53
Add details about dependencies
nickrobinson251 Aug 11, 2019
82557ea
Remove ChainRules as it has no user-facing names
nickrobinson251 Aug 11, 2019
6b18cac
Correct package name `NaNMath`
nickrobinson251 Aug 11, 2019
079322c
Remove uses of add and mul from tests because they have been removed …
oxinabox Aug 30, 2019
e4ff2f1
PR preview docs (#105)
oxinabox Sep 20, 2019
12f97fb
introdocs + demo + instructions on writing good rules (#103)
oxinabox Sep 25, 2019
8e8b036
Add Logo (#113)
oxinabox Sep 27, 2019
987cc9f
Fix TeX in docs
YingboMa Dec 21, 2019
129fd55
Fix a few spelling mistakes and formatting issues
YingboMa Dec 21, 2019
40c0713
Remove Wirtinger
YingboMa Jan 11, 2020
e3307d9
Add difference between `Zero` and `DoesNotExist` to FAQ (#156)
oxinabox Jan 20, 2020
47aae0a
Doc updates for ChainRulesCore 0.5 (#152)
oxinabox Jan 20, 2020
f9dc97f
Remove TODO sections in docs (#150)
oxinabox Jan 20, 2020
191e8c2
Break up giant single page of docs (#158)
oxinabox Jan 21, 2020
deeca7b
Remove `store!`, `accumulate`, `accumulate!` (#161)
nickrobinson251 Jan 22, 2020
e0e424f
Make docs build with travis CI
oxinabox Jan 22, 2020
342c092
Add Manifest
oxinabox Jan 22, 2020
ffa1f16
Update docs/make.jl
oxinabox Jan 22, 2020
9f33fc2
update link in readme
oxinabox Jan 22, 2020
b0ef3c2
Apply suggestions from code review
oxinabox Jan 22, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 14 additions & 10 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,25 @@ julia:
- 1.2
- 1.3
- nightly
matrix:
jobs:
allow_failures:
- julia: 1.3
- julia: nightly
- julia: 1.3
- julia: nightly
include:
- stage: "Documentation"
julia: 1.0
os: linux
script:
- julia --project=docs/ -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate()'
- julia --project=docs/ docs/make.jl
after_success: skip

after_success:
- julia -e 'using Pkg; Pkg.add("Coverage"); using Coverage; Coveralls.submit(Coveralls.process_folder())'
notifications:
email:
recipients:
- nightly-rse@invenia.ca
on_success: never
on_failure: always
if: type = cron
# uncomment the following lines to override the default test script
#script:
# - if [[ -a .git/shallow ]]; then git fetch --unshallow; fi
# - julia -e 'Pkg.clone(pwd()); Pkg.build("ChainRulesCore"); Pkg.test("ChainRulesCore"; coverage=true)'
after_success:
# push coverage results to Coveralls
- julia -e 'using Pkg; Pkg.add("Coverage"); using Coverage; Coveralls.submit(Coveralls.process_folder())'
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
[![Coveralls](https://coveralls.io/repos/github/JuliaDiff/ChainRulesCore.jl/badge.svg?branch=master)](https://coveralls.io/github/JuliaDiff/ChainRulesCore.jl?branch=master)
[![PkgEval](https://juliaci.github.io/NanosoldierReports/pkgeval_badges/C/ChainRulesCore.svg)](https://juliaci.github.io/NanosoldierReports/pkgeval_badges/report.html)

[![Docs](https://img.shields.io/badge/docs-latest-blue.svg)](https://JuliaDiff.github.io/ChainRules.jl/latest)
**Docs:**
[![](https://img.shields.io/badge/docs-master-blue.svg)](https://JuliaDiff.github.io/ChainRulesCore.jl/dev)
[![](https://img.shields.io/badge/docs-stable-blue.svg)](https://JuliaDiff.github.io/ChainRulesCore.jl/stable)

The ChainRulesCore package provides a light-weight dependency for defining sensitivities for functions in your packages, without you needing to depend on ChainRules itself.

Expand Down
133 changes: 133 additions & 0 deletions docs/Manifest.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
[[Base64]]
uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"

[[ChainRules]]
deps = ["ChainRulesCore", "LinearAlgebra", "Reexport", "Requires", "Statistics"]
git-tree-sha1 = "906cb2ae273ddbc559490117faa7abd36c98f51a"
uuid = "082447d4-558c-5d27-93f4-14fc19e9eca2"
version = "0.3.2"

[[ChainRulesCore]]
deps = ["MuladdMacro"]
git-tree-sha1 = "2d67fd76f99ffba4059e55be324b24bf38582a38"
repo-rev = "ox/movedoctsD2"
repo-url = ".."
uuid = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
version = "0.6.1"

[[Dates]]
deps = ["Printf"]
uuid = "ade2ca70-3891-5945-98fb-dc099432e06a"

[[Distributed]]
deps = ["LinearAlgebra", "Random", "Serialization", "Sockets"]
uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b"

[[DocStringExtensions]]
deps = ["LibGit2", "Markdown", "Pkg", "Test"]
git-tree-sha1 = "88bb0edb352b16608036faadcc071adda068582a"
uuid = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"
version = "0.8.1"

[[Documenter]]
deps = ["Base64", "DocStringExtensions", "InteractiveUtils", "JSON", "LibGit2", "Logging", "Markdown", "REPL", "Test", "Unicode"]
git-tree-sha1 = "d45c163c7a3ae293c15361acc52882c0f853f97c"
uuid = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
version = "0.23.4"

[[InteractiveUtils]]
deps = ["LinearAlgebra", "Markdown"]
uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240"

[[JSON]]
deps = ["Dates", "Mmap", "Parsers", "Unicode"]
git-tree-sha1 = "b34d7cef7b337321e97d22242c3c2b91f476748e"
uuid = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
version = "0.21.0"

[[LibGit2]]
uuid = "76f85450-5226-5b5a-8eaa-529ad045b433"

[[Libdl]]
uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb"

[[LinearAlgebra]]
deps = ["Libdl"]
uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"

[[Logging]]
uuid = "56ddb016-857b-54e1-b83d-db4d58db5568"

[[Markdown]]
deps = ["Base64"]
uuid = "d6f4376e-aef5-505a-96c1-9c027394607a"

[[Mmap]]
uuid = "a63ad114-7e13-5084-954f-fe012c677804"

[[MuladdMacro]]
git-tree-sha1 = "c6190f9a7fc5d9d5915ab29f2134421b12d24a68"
uuid = "46d2c3a1-f734-5fdb-9937-b9b9aeba4221"
version = "0.2.2"

[[Parsers]]
deps = ["Dates", "Test"]
git-tree-sha1 = "0139ba59ce9bc680e2925aec5b7db79065d60556"
uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0"
version = "0.3.10"

[[Pkg]]
deps = ["Dates", "LibGit2", "Markdown", "Printf", "REPL", "Random", "SHA", "UUIDs"]
uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"

[[Printf]]
deps = ["Unicode"]
uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7"

[[REPL]]
deps = ["InteractiveUtils", "Markdown", "Sockets"]
uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb"

[[Random]]
deps = ["Serialization"]
uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"

[[Reexport]]
deps = ["Pkg"]
git-tree-sha1 = "7b1d07f411bc8ddb7977ec7f377b97b158514fe0"
uuid = "189a3867-3050-52da-a836-e630ba90ab69"
version = "0.2.0"

[[Requires]]
deps = ["UUIDs"]
git-tree-sha1 = "999513b7dea8ac17359ed50ae8ea089e4464e35e"
uuid = "ae029012-a4dd-5104-9daa-d747884805df"
version = "1.0.0"

[[SHA]]
uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce"

[[Serialization]]
uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b"

[[Sockets]]
uuid = "6462fe0b-24de-5631-8697-dd941f90decc"

[[SparseArrays]]
deps = ["LinearAlgebra", "Random"]
uuid = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"

[[Statistics]]
deps = ["LinearAlgebra", "SparseArrays"]
uuid = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"

[[Test]]
deps = ["Distributed", "InteractiveUtils", "Logging", "Random"]
uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[[UUIDs]]
deps = ["Random"]
uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"

[[Unicode]]
uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5"
7 changes: 7 additions & 0 deletions docs/Project.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[deps]
ChainRules = "082447d4-558c-5d27-93f4-14fc19e9eca2"
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"

[compat]
Documenter = "~0.23"
40 changes: 40 additions & 0 deletions docs/make.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using ChainRules
using ChainRulesCore
using Documenter

@show ENV

makedocs(
modules=[ChainRules, ChainRulesCore],
format=Documenter.HTML(prettyurls=false, assets = ["assets/chainrules.css"]),
sitename="ChainRules",
authors="Jarrett Revels and other contributors",
pages=[
"Introduction" => "index.md",
"FAQ" => "FAQ.md",
"Writing Good Rules" => "writing_good_rules.md",
"API" => "api.md",
],
)

const repo = "github.com/JuliaDiff/ChainRulesCore.jl.git"
const PR = get(ENV, "TRAVIS_PULL_REQUEST", "false")
if PR == "false"
# Normal case, only deply docs if merging to master or release tagged
deploydocs(repo=repo)
else
@info "Deploying review docs for PR #$PR"
# TODO: remove most of this once https://github.com/JuliaDocs/Documenter.jl/issues/1131 is resolved
mattBrzezinski marked this conversation as resolved.
Show resolved Hide resolved

# Overwrite Documenter's function for generating the versions.js file
foreach(Base.delete_method, methods(Documenter.Writers.HTMLWriter.generate_version_file))
Documenter.Writers.HTMLWriter.generate_version_file(_, _) = nothing
# Overwrite necessary environment variables to trick Documenter to deploy
ENV["TRAVIS_PULL_REQUEST"] = "false"
ENV["TRAVIS_BRANCH"] = "master"

deploydocs(
devurl="preview-PR$(PR)",
repo=repo,
)
end
69 changes: 69 additions & 0 deletions docs/src/FAQ.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# FAQ

## What is up with the different symbols?

### `Δx`, `∂x`, `dx`
ChainRules uses these perhaps atypically.
As a notation that is the same across propagators, regardless of direction (incontrast see `ẋ` and `x̄` below).

- `Δx` is the input to a propagator, (i.e a _seed_ for a _pullback_; or a _perturbation_ for a _pushforward_)
- `∂x` is the output of a propagator
- `dx` could be either `input` or `output`


### dots and bars: ``\dot{y} = \dfrac{∂y}{∂x} = \overline{x}``
- `v̇` is a derivative of the input moving forward: ``v̇ = \frac{∂v}{∂x}`` for input ``x``, intermediate value ``v``.
mattBrzezinski marked this conversation as resolved.
Show resolved Hide resolved
- `v̄` is a derivative of the output moving backward: ``v̄ = \frac{∂y}{∂v}`` for output ``y``, intermediate value ``v``.

### others
- `Ω` is often used as the return value of the function. Especially, but not exclusively, for scalar functions.
- `ΔΩ` is thus a seed for the pullback.
- `∂Ω` is thus the output of a pushforward.


Copy link
Member

Choose a reason for hiding this comment

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

Suggested change

## Why does `rrule` return the primal function evaluation?
You might wonder why `frule(f, x)` returns `f(x)` and the derivative of `f` at `x`, and similarly for `rrule` returning `f(x)` and the pullback for `f` at `x`.
Why not just return the pushforward/pullback, and let the user call `f(x)` to get the answer separately?

There are three reasons the rules also calculate the `f(x)`.
1. For some rules an alternative way of calculating `f(x)` can give the same answer while also generating intermediate values that can be used in the calculations required to propagate the derivative.
2. For many `rrule`s the output value is used in the definition of the pullback. For example `tan`, `sigmoid` etc.
3. For some `frule`s there exists a single, non-separable operation that will compute both derivative and primal result. For example many of the methods for [differential equation sensitivity analysis](https://docs.juliadiffeq.org/stable/analysis/sensitivity/#sensitivity-1).

## Where are the derivatives for keyword arguments?
_pullbacks_ do not return a sensitivity for keyword arguments;
similarly _pushfowards_ do not accept a perturbation for keyword arguments.
This is because in practice functions are very rarely differentiable with respect to keyword arguments.
As a rule keyword arguments tend to control side-effects, like logging verbosity,
or to be functionality changing to perform a different operation, e.g. `dims=3`, and thus not differentiable.
To the best of our knowledge no Julia AD system, with support for the definition of custom primitives, supports differentiating with respect to keyword arguments.
At some point in the future ChainRules may support these. Maybe.


Copy link
Member

Choose a reason for hiding this comment

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

Suggested change

Seeing this in a few places I think just a consistency of double or single spacing between blocks is best.

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 my preference is double between blocks, single between paragraphs ?
I don't think it's a big deal either way.

Maybe we should get a markdown autoformatter?

## What is the difference between `Zero` and `DoesNotExist` ?
`Zero` and `DoesNotExist` act almost exactly the same in practice: they result in no change whenever added to anything.
Odds are if you write a rule that returns the wrong one everything will just work fine.
We provide both to allow for clearer writing of rules, and easier debugging.

`Zero()` represents the fact that if one perturbs (adds a small change to) the matching primal there will be no change in the behavour of the primal function.
For example in `fst(x,y) = x`, then the derivative of `fst` with respect to `y` is `Zero()`.
`fst(10, 5) == 10` and if we add `0.1` to `5` we still get `fst(10, 5.1)=10`.

`DoesNotExist()` represents the fact that if one perturbs the matching primal, the primal function will now error.
For example in `access(xs, n) = xs[n]` then the derivative of `access` with respect to `n` is `DoesNotExist()`.
`access([10, 20, 30], 2) = 20`, but if we add `0.1` to `2` we get `access([10, 20, 30], 2.1)` which errors as indexing can't be applied at fractional indexes.


## When to use ChainRules vs ChainRulesCore?

Copy link
Member

Choose a reason for hiding this comment

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

Suggested change

[ChainRulesCore.jl](https://github.com/JuliaDiff/ChainRulesCore.jl) is a light-weight dependency for defining rules for functions in your packages, without you needing to depend on ChainRules itself. It has no dependencies of its own.

[ChainRules.jl](https://github.com/JuliaDiff/ChainRules.jl) provides the full functionality, in particular it has all the rules for Base Julia and the standard libraries. Its thus a much heavier package to load.

If you only want to define rules, not use them then you probably only want to load ChainRulesCore.
AD systems making use of ChainRules should load ChainRules (rather than ChainRulesCore).

## Where should I put my rules?
In general, we recommend adding custom sensitivities to your own packages with ChainRulesCore, rather than adding them to ChainRules.jl.

A few packages currently SpecialFunctions.jl and NaNMath.jl are in ChainRules.jl but this is a short-term measure.
5 changes: 5 additions & 0 deletions docs/src/api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# API Documentation

```@autodocs
Modules = [ChainRulesCore]
```
78 changes: 78 additions & 0 deletions docs/src/assets/chainrules.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/* Links */

a {
color: #4595D1;
}

a:hover, a:focus {
color: #194E82;
}

/* Navigation */

nav.toc ul a:hover,
nav.toc ul.internal a:hover {
color: #FFFFFF;
background-color: #4595D1;
}

nav.toc ul .toctext {
color: #FFFFFF;
}

nav.toc {
box-shadow: none;
color: #FFFFFF;
background-color: #194E82;
}

nav.toc li.current > .toctext {
color: #FFFFFF;
background-color: #4595D1;
border-top-width: 0px;
border-bottom-width: 0px;
}

nav.toc ul.internal a {
color: #194E82;
background-color: #FFFFFF;
}

/* Text */

article#docs a.nav-anchor {
color: #194E82;
}

article#docs blockquote {
font-style: italic;
}

/* Terminology Block */

div.admonition.terminology div.admonition-title:before {
content: "Terminology: ";
font-family: inherit;
font-weight: bold;
}
div.admonition.terminology div.admonition-title {
background-color: #FFEC8B;
}

div.admonition.terminology div.admonition-text {
background-color: #FFFEDD;
}

/* Code */

code .hljs-meta {
color: #4595D1;
}

code .hljs-keyword {
color: #194E82;
}

pre, code {
font-family: "Liberation Mono", "Consolas", "DejaVu Sans Mono", "Ubuntu Mono", "andale mono", "lucida console", monospace;
}
Loading