pdf files; edits

This commit is contained in:
jverzani
2024-10-15 17:17:25 -04:00
parent c1629e4f1a
commit 30086f9517
50 changed files with 1307 additions and 86 deletions

View File

@@ -0,0 +1,28 @@
[deps]
BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"
CalculusWithJulia = "a2e0e22d-7d4c-5312-9169-8b992201a882"
ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210"
GLMakie = "e9467ef8-e4e7-5192-8a1a-b1aee30e663a"
GeometryBasics = "5c1252a2-5f33-56bf-86c9-59e7332b4326"
IJulia = "7073ff75-c697-5162-941a-fcdaad2a7d2a"
Implicit3DPlotting = "d997a800-832a-4a4c-b340-7dddf3c1ad50"
Integrals = "de52edbc-65ea-441a-8357-d3a637375a31"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
Meshing = "e6723b4c-ebff-59f1-b4b7-d97aa5274f73"
ModelingToolkit = "961ee093-0014-501f-94e3-6117800e7a78"
NonlinearSolve = "8913a72c-1f9b-4ce2-8d82-65094dcecaec"
Optimization = "7f7a1694-90dd-40f0-9382-eb1efda571ba"
OptimizationOptimJL = "36348300-93cb-4f02-beb5-3c3902f8871e"
PlotUtils = "995b91a9-d308-5afd-9ec6-746e21dbc043"
PlotlyBase = "a03496cd-edff-5a9b-9e67-9cda94a718b5"
PlotlyKaleido = "f2990250-8cf9-495f-b13a-cce12b45703c"
PlotlyLight = "ca7969ec-10b3-423e-8d99-40f33abb42bf"
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
QuadGK = "1fd47b50-473d-5c70-9696-f719f8f3bcdc"
Roots = "f2b01f46-fcfa-551c-844a-d8ac1e96c665"
SplitApplyCombine = "03a91e81-4c3e-53e1-a0a4-9c0c8f19dd66"
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
SymPy = "24249f21-da20-56a4-8eb1-6a02cf4ae2e6"
SymbolicLimits = "19f23fe9-fdab-4a78-91af-e7b7767979c3"
SymbolicNumericIntegration = "78aadeae-fbc0-11eb-17b6-c7ec0477ba9e"
Symbolics = "0c5d862f-8b57-4792-8d23-62f2024744c7"

View File

@@ -304,11 +304,11 @@ x0 = [4.0]
prob = OptimizationProblem(F, x0)
```
The problem is solved through the common interface with a specified method, in this case `Newton`:
The problem is solved through the common interface with a specified method, in this case `NelderMead`:
```{julia}
soln = solve(prob, Newton())
soln = solve(prob, NelderMead())
```
:::{.callout-note}

View File

@@ -0,0 +1 @@
../alternatives.qmd

View File

@@ -0,0 +1,18 @@
module Make
# makefile for generating typst pdfs
# per directory usage
dir = "alternatives"
files = (
"symbolics",
"SciML",
"plotly_plotting",
"makie_plotting",
)
include("../_make_pdf.jl")
main()
end

View File

@@ -867,52 +867,31 @@ end
To plot the equation $F(x,y,z)=0$, for $F$ a scalar-valued function, again the implicit function theorem says that, under conditions, near any solution $(x,y,z)$, $z$ can be represented as a function of $x$ and $y$, so the graph will look likes surfaces stitched together. The `Implicit3DPlotting` package takes an approach like `ImplicitPlots` to represent these surfaces. It replaces the `Contour` package computation with a $3$-dimensional alternative provided through the `Meshing` and `GeometryBasics` packages.
The `Implicit3DPlotting` package needs some maintenance, so we borrow the main functionality and wrap it into a function:
```{julia}
import Meshing
import GeometryBasics
function make_mesh(xlims, ylims, zlims, f,
M = Meshing.MarchingCubes(); # or Meshing.MarchingTetrahedra()
samples=(35, 35, 35),
)
lims = extrema.((xlims, ylims, zlims))
Δ = xs -> last(xs) - first(xs)
xs = Vec(first.(lims))
Δxs = Vec(Δ.(lims))
GeometryBasics.Mesh(f, Rect(xs, Δxs), M; samples = samples)
end
using Implicit3DPlotting
```
The `make_mesh` function creates a mesh that can be visualized with the `wireframe` or `mesh` plotting functions.
This example, plotting an implicitly defined sphere, comes from the documentation of `Implicit3DPlotting`. The `f` in `make_mesh` is a scalar-valued function of a vector:
This example, plotting an implicitly defined sphere, comes from the documentation of `Implicit3DPlotting`. The `f` to be plotted is a scalar-valued function of a vector:
```{julia}
f(x) = sum(x.^2) - 1
xs = ys = zs = (-5, 5)
m = make_mesh(xs, ys, zs, f)
wireframe(m)
xlims = ylims = zlims = (-5, 5)
plot_implicit_surface(f; xlims, ylims, zlims)
```
Here we visualize an intersection of a sphere with another figure:
```{julia}
r₂(x) = sum(x.^2) - 5/4 # a sphere
r₄(x) = sum(x.^4) - 1
xs = ys = zs = -2:2
m2,m4 = make_mesh(xs, ys, zs, r₂), make_mesh(xs, ys, zs, r₄)
wireframe(m4, color=:yellow)
wireframe!(m2, color=:red)
xlims = ylims = zlims = (-2, 2)
p = plot_implicit_surface(r₂; xlims, ylims, zlims, color=:yellow)
plot_implicit_surface!(p, r₄; xlims, ylims, zlims, color=:red)
current_figure()
```
@@ -921,9 +900,8 @@ This example comes from [Wikipedia](https://en.wikipedia.org/wiki/Implicit_surfa
```{julia}
f(x,y,z) = 2y*(y^2 -3x^2)*(1-z^2) + (x^2 +y^2)^2 - (9z^2-1)*(1-z^2)
zs = ys = xs = range(-5/2, 5/2, length=100)
m = make_mesh(xs, ys, zs, x -> f(x...))
wireframe(m)
xlims = ylims = zlims = (-5/2, 5/2)
plot_implicit_surface(x -> f(x...); xlims, ylims, zlims)
```
(This figure does not render well through `contour(xs, ys, zs, f, levels=[0])`, as the hole is not shown.)
@@ -937,9 +915,8 @@ function cassini(λ, ps = ((1,0,0), (-1, 0, 0)))
n = length(ps)
x -> prod(norm(x .- p) for p ∈ ps) - λ^n
end
xs = ys = zs = range(-2, 2, length=100)
m = make_mesh(xs, ys, zs, cassini(1.05))
wireframe(m)
xlims = ylims = zlims = (-2, 2)
plot_implicit_surface(cassini(1.05); xlims, ylims, zlims)
```
## Vector fields. Visualizations of $f:R^2 \rightarrow R^2$

View File

@@ -140,8 +140,8 @@ typeof(sin(x)), typeof(Symbolics.value(sin(x)))
The `TermInterface` package is used by `SymbolicUtils` to explore the tree structure of an expression. The main methods are (cf. [SymbolicUtils.jl](https://symbolicutils.juliasymbolics.org/#expression_interface)):
* `istree(ex)`: `true` if `ex` is not a *leaf* node (like a symbol or numeric literal)
* `operation(ex)`: the function being called (if `istree` returns `true`)
* `iscall(ex)`: `true` if `ex` is not a *leaf* node (like a symbol or numeric literal). The old name was `istree`.
* `operation(ex)`: the function being called (if `iscall` returns `true`)
* `arguments(ex)`: the arguments to the function being called
* `symtype(ex)`: the inferred type of the expression
@@ -163,7 +163,7 @@ arguments(ex) # `+` is n-ary, in this case with 3 arguments
```
```{julia}
ex1 = arguments(ex)[3] # terms have been reordered
ex1 = arguments(ex)[2] # terms have been reordered
operation(ex1) # operation for `x^2` is `^`
```
@@ -172,10 +172,10 @@ a, b = arguments(ex1)
```
```{julia}
istree(ex1), istree(a)
iscall(ex1), iscall(a)
```
Here `a` is not a "tree", as it has no operation or arguments, it is just a variable (the `x` variable).
Here `a` is not a call, as it has no operation or arguments, it is just a variable (the `x` variable).
The value of `symtype` is the *inferred* type of an expression, which may not match the actual type. For example,
@@ -199,7 +199,7 @@ As an example, we write a function to find the free symbols in a symbolic expres
import Symbolics.SymbolicUtils: issym
free_symbols(ex) = (s=Set(); free_symbols!(s, ex); s)
function free_symbols!(s, ex)
if istree(ex)
if iscall(ex)
for a ∈ arguments(ex)
free_symbols!(s, a)
end
@@ -660,11 +660,11 @@ or
eqs = [5x + 2y, 6x + 3y] .~ [1, 2]
```
The `Symbolics.solve_for` function can solve *linear* equations. For example,
The `Symbolics.symbolic_linear_solve` function can solve *linear* equations. For example,
```{julia}
Symbolics.solve_for(eqs, [x, y])
Symbolics.symbolic_linear_solve(eqs, [x, y])
```
The coefficients can be symbolic. Two examples could be:
@@ -673,7 +673,7 @@ The coefficients can be symbolic. Two examples could be:
```{julia}
@variables m b x y
eq = y ~ m*x + b
Symbolics.solve_for(eq, x)
Symbolics.symbolic_linear_solve(eq, x)
```
```{julia}
@@ -683,13 +683,30 @@ eqs = R*X .~ b
```
```{julia}
Symbolics.solve_for(eqs, [x,y])
Symbolics.symbolic_linear_solve(eqs, [x,y])
```
### Limits
Many symbolic limits involving exponentials and logarithms can be
computed in Symbolics, as of recent versions. The underlying package
is `SymbolicLimits`. This package is in development. Below we use the
unwrapped version of the variable. We express limits as $x$ goes to
infinity, which can be achieved by rewriting:
As of writing, there is no extra functionality provided by `Symbolics` for computing limits.
```{julia}
@variables x
𝑥 = x.val # unwrapped
F(x) = exp(x+exp(-x))-exp(x)
limit(F(𝑥), 𝑥, Inf)
```
Or
```{julia}
F(x) = log(log(x*exp(x*exp(x))+1))-exp(exp(log(log(x))+1/x))
limit(F(𝑥), 𝑥, Inf)
```
### Derivatives
@@ -708,7 +725,7 @@ Or to find a critical point:
```{julia}
Symbolics.solve_for(yp ~ 0, x) # linear equation to solve
Symbolics.symbolic_linear_solve(yp ~ 0, x) # linear equation to solve
```
The derivative computation can also be broken up into an expression indicating the derivative and then a function to apply the derivative rules:
@@ -726,7 +743,8 @@ and then
expand_derivatives(D(y))
```
Using `Differential`, differential equations can be specified. An example was given in [ODEs](../ODEs/differential_equations.html), using `ModelingToolkit`.
Using `Differential`, differential equations can be specified. An example was given in [ODEs](../ODEs/differential_equations.html),
using `ModelingToolkit`.
Higher order derivatives can be done through composition:
@@ -774,12 +792,6 @@ Symbolics.jacobian(eqs, [x,y])
### Integration
::: {.callout-note}
#### This area is very much WIP
The use of `SymbolicNumericIntegration` below is currently broken.
:::
The `SymbolicNumericIntegration` package provides a means to integrate *univariate* expressions through its `integrate` function.
@@ -838,18 +850,10 @@ substitute(ΣqᵢΘᵢ, d)
The package provides an algorithm for the creation of candidates and the means to solve when possible. The `integrate` function is the main entry point. It returns three values: `solved`, `unsolved`, and `err`. The `unsolved` is the part of the integrand which can not be solved through this package. It is `0` for a given problem when `integrate` is successful in identifying an antiderivative, in which case `solved` is the answer. The value of `err` is a bound on the numerical error introduced by the algorithm.
::: {.callout-note}
### This is currently broken
The following isn't working with `SymbolicNumericIntegration` version `v"1.4.0"`. For now, the cells are not evaluated.
:::
To see, we have:
```{julia}
#| eval: false
using SymbolicNumericIntegration
@variables x
@@ -871,7 +875,6 @@ Powers of trig functions have antiderivatives, as can be deduced using integrati
```{julia}
#| eval: false
u,v,w = integrate(sin(x)^5)
```
@@ -879,7 +882,6 @@ The derivative of `u` matches up to some numeric tolerance:
```{julia}
#| eval: false
Symbolics.derivative(u, x) - sin(x)^5
```