diff --git a/docs/make.jl b/docs/make.jl index 1ecc9e3..f7c6bcb 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -24,11 +24,8 @@ makedocs(; pages=[ "Getting Started" => "index.md", "User Documentation" => - ["Limitations" => "user/limitations.md", "API Reference" => "user/api.md"], - "Developer Documentation" => [ - "How SCT works" => "dev/how_it_works.md", - "Internals Reference" => "dev/api.md", - ], + ["user/global_vs_local.md", "user/limitations.md", "user/api.md"], + "Developer Documentation" => ["dev/how_it_works.md", "dev/api.md"], ], warnonly=[:missing_docs], ) diff --git a/docs/src/dev/how_it_works.md b/docs/src/dev/how_it_works.md index 38e909b..f265aa2 100644 --- a/docs/src/dev/how_it_works.md +++ b/docs/src/dev/how_it_works.md @@ -34,11 +34,12 @@ Sparsity patterns correspond to the mask of non-zero values in the gradient and Instead of saving the values of individual partial derivatives, they can efficiently be represented by the set of indices corresponding to non-zero values: * Gradient patterns are represented by sets of indices $\left\{i \;\big|\; \left(\nabla f(\mathbf{x})\right)_{i} \neq 1\right\}$ -* Local Hessian patterns are represented by sets of index tuples $\left\{(i, j) \;\Big|\; \left(\nabla^2 f(\mathbf{x})\right)_{i,j} \neq 1\right\}$ +* Hessian patterns are represented by sets of index tuples $\left\{(i, j) \;\Big|\; \left(\nabla^2 f(\mathbf{x})\right)_{i,j} \neq 1\right\}$ !!! warning "Global vs. Local" - Global sparsity patterns are the index sets over all $\mathbf{x}\in\mathbb{R}^n$, + As shown in the page [*"Global vs. Local"*](@ref global-vs-local), + global sparsity patterns are the index sets over all $\mathbf{x}\in\mathbb{R}^n$, whereas local patterns are the index sets for a given point $\mathbf{x}$. For a given function $f$, global sparsity patterns are therefore always supersets of local sparsity patterns and more "conservative" in the sense that they are less sparse. diff --git a/docs/src/user/global_vs_local.md b/docs/src/user/global_vs_local.md new file mode 100644 index 0000000..fa7c9a6 --- /dev/null +++ b/docs/src/user/global_vs_local.md @@ -0,0 +1,54 @@ +# [Global vs. Local Sparsity](@id global-vs-local) + +Let's motivate the difference between local and global sparsity patterns by taking a look at the function $f(\mathbf{x}) = x_1x_2$. +The corresponding Jacobian is: + +```math +J_f = \begin{bmatrix} + \frac{\partial f}{\partial x_1} & + \frac{\partial f}{\partial x_2} +\end{bmatrix} += +\begin{bmatrix} + x_2 & x_1 +\end{bmatrix} +``` + +Depending on the values of $\mathbf{x}$, the resulting **local** Jacobian sparsity pattern could be either: +* $[1\; 1]$ for $x_1 \neq 0$, $x_2 \neq 0$ +* $[1\; 0]$ for $x_1 = 0$, $x_2 \neq 0$ +* $[0\; 1]$ for $x_1 \neq 0$, $x_2 = 0$ +* $[0\; 0]$ for $x_1 = 0$, $x_2 = 0$ + +These are computed by [`TracerLocalSparsityDetector`](@ref): + +```@repl localvsglobal +using SparseConnectivityTracer +method = TracerLocalSparsityDetector(); + +f(x) = x[1]*x[2]; + +jacobian_sparsity(f, [1, 1], method) +jacobian_sparsity(f, [0, 1], method) +jacobian_sparsity(f, [1, 0], method) +jacobian_sparsity(f, [0, 0], method) +``` + +In contrast to this, [`TracerSparsityDetector`](@ref) computes a conservative union over all sparsity patterns in $\mathbf{x} \in \mathbb{R}^2$. +The resulting **global** pattern therefore does not depend on the input. +All of the following function calls are equivalent: + +```@repl localvsglobal +method = TracerSparsityDetector(); + +jacobian_sparsity(f, [1, 1], method) +jacobian_sparsity(f, [0, 1], method) +jacobian_sparsity(f, [1, 0], method) +jacobian_sparsity(f, [0, 0], method) +jacobian_sparsity(f, rand(2), method) +``` + +!!! tip "Global vs. Local" + Global sparsity patterns are the union of all local sparsity patterns over the entire input domain. + For a given function, they are therefore always supersets of local sparsity patterns + and more "conservative" in the sense that they are less sparse.